Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package procdump for openSUSE:Factory checked in at 2022-05-05 23:07:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/procdump (Old) and /work/SRC/openSUSE:Factory/.procdump.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "procdump" Thu May 5 23:07:39 2022 rev:5 rq:975237 version:1.2 Changes: -------- --- /work/SRC/openSUSE:Factory/procdump/procdump.changes 2020-06-07 21:39:28.953671532 +0200 +++ /work/SRC/openSUSE:Factory/.procdump.new.1538/procdump.changes 2022-05-05 23:08:24.817708612 +0200 @@ -1,0 +2,10 @@ +Thu May 5 15:40:06 UTC 2022 - Ferdinand Thiessen <r...@fthiessen.de> + +- Update to version 1.2 + * Added -G Signal trigger + * Added -o custom path/file name for core dumps + * Small fix for multiple definition with GCC 10+ + (fixes procdump-gcc10.patch that is dropped by now) + * Small bug fixes + +------------------------------------------------------------------- Old: ---- procdump-1.1.1.tar.gz procdump-gcc10.patch New: ---- procdump-1.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ procdump.spec ++++++ --- /var/tmp/diff_new_pack.yZJrW7/_old 2022-05-05 23:08:25.269709176 +0200 +++ /var/tmp/diff_new_pack.yZJrW7/_new 2022-05-05 23:08:25.273709181 +0200 @@ -1,7 +1,7 @@ # # spec file for package procdump # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,14 +17,12 @@ Name: procdump -Version: 1.1.1 +Version: 1.2 Release: 0 Summary: Process coredump emitter using performance triggers License: MIT URL: https://github.com/Microsoft/ProcDump-for-Linux Source0: https://github.com/Microsoft/ProcDump-for-Linux/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz -# PATCH-FIX-UPSTREAM procdump-gcc10.patch -Patch0: procdump-gcc10.patch BuildRequires: pkgconfig(zlib) %description ++++++ procdump-1.1.1.tar.gz -> procdump-1.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/CONTRIBUTING.md new/ProcDump-for-Linux-1.2/CONTRIBUTING.md --- old/ProcDump-for-Linux-1.1.1/CONTRIBUTING.md 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/CONTRIBUTING.md 2021-09-15 00:53:53.000000000 +0200 @@ -10,7 +10,7 @@ ## Build and run from source ### Environment -* Linux OS (dev team is using Ubuntu 16.04) +* Linux OS (dev team is using Ubuntu 18.04) * Development can be done on Windows Subsystem for Linux (WSL), but ProcDump cannot be executed in that environment * git * GDB diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/INSTALL.md new/ProcDump-for-Linux-1.2/INSTALL.md --- old/ProcDump-for-Linux-1.1.1/INSTALL.md 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/INSTALL.md 2021-09-15 00:53:53.000000000 +0200 @@ -1,6 +1,6 @@ # Install ProcDump -## Ubuntu 16.04, 18.04 & 19.10 +## Ubuntu 16.04, 18.04 & 20.04 #### 1. Register Microsoft key and feed ```sh wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb @@ -51,11 +51,11 @@ sudo apt-get install procdump ``` -## Fedora 29 +## Fedora 31 #### 1. Register Microsoft key and feed ```sh sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/29/prod.repo +sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/31/prod.repo ``` #### 2. Install Procdump @@ -63,11 +63,11 @@ sudo dnf install procdump ``` -## Fedora 30 +## Fedora 32 #### 1. Register Microsoft key and feed ```sh sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/30/prod.repo +sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/32/prod.repo ``` #### 2. Install Procdump @@ -75,23 +75,23 @@ sudo dnf install procdump ``` -## Fedora 31 +## RHEL 7 #### 1. Register Microsoft key and feed ```sh sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/31/prod.repo +sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/rhel/7/prod.repo ``` #### 2. Install Procdump ```sh -sudo dnf install procdump +sudo yum install procdump ``` -## RHEL 7 +## RHEL 8 #### 1. Register Microsoft key and feed ```sh sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/rhel/7/prod.repo +sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/rhel/8/prod.repo ``` #### 2. Install Procdump @@ -99,11 +99,10 @@ sudo yum install procdump ``` -## RHEL 8 +## CentOS 7 #### 1. Register Microsoft key and feed ```sh -sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo wget -q -O /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/rhel/8/prod.repo +sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm ``` #### 2. Install Procdump @@ -111,10 +110,10 @@ sudo yum install procdump ``` -## CentOS 7 +## CentOS 8 #### 1. Register Microsoft key and feed ```sh -sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm +sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm ``` #### 2. Install Procdump @@ -157,4 +156,4 @@ #### 2. Install Procdump ```sh sudo zypper install procdump -``` \ No newline at end of file +``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/Makefile new/ProcDump-for-Linux-1.2/Makefile --- old/ProcDump-for-Linux-1.1.1/Makefile 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/Makefile 2021-09-15 00:53:53.000000000 +0200 @@ -35,7 +35,7 @@ $(BUILDDIR)/SOURCES $(BUILDDIR)/SPECS $(BUILDDIR)/BUILD $(BUILDDIR)/BUILDROOT # package details -PKG_VERSION=1.1.1 +PKG_VERSION=1.2 all: clean build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/README.md new/ProcDump-for-Linux-1.2/README.md --- old/ProcDump-for-Linux-1.1.1/README.md 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/README.md 2021-09-15 00:53:53.000000000 +0200 @@ -1,4 +1,4 @@ -# ProcDump [](https://oss-sysinternals.visualstudio.com/Procdump%20for%20Linux/_build/latest?definitionId=10&branchName=master) +# ProcDump [](https://oss-sysinternals.visualstudio.com/Procdump%20for%20Linux/_build/latest?definitionId=21&branchName=master) ProcDump is a Linux reimagining of the classic ProcDump tool from the Sysinternals suite of tools for Windows. ProcDump provides a convenient way for Linux developers to create core dumps of their application based on performance triggers.  @@ -8,13 +8,13 @@ ## Requirements * Minimum OS: * Red Hat Enterprise Linux / CentOS 7 - * Fedora 26 - * Ubuntu 14.04 LTS + * Fedora 29 + * Ubuntu 16.04 LTS * `gdb` >= 7.6.1 * `zlib` (build-time only) ## Install ProcDump -Checkout our [install instructions](INSTALL.md) for ditribution specific steps to install Procdump. +Checkout our [install instructions](INSTALL.md) for distribution specific steps to install Procdump. ## Build ProcDump from Scratch To build from scratch you'll need to have a C compiler (supporting C11), `zlib`, and a `make` utility installed. Then simply run: @@ -47,10 +47,12 @@ -M Trigger core dump generation when memory commit exceeds or equals specified value (MB) -m Trigger core dump generation when when memory commit is less than specified value (MB) -T Trigger when thread count exceeds or equals specified value. - -F Trigger when filedescriptor count exceeds or equals specified value. + -F Trigger when file descriptor count exceeds or equals specified value. + -G Trigger when signal with the specified value (numeric) is sent (uses PTRACE and will affect performance of target process). -I Polling frequency in milliseconds (default is 1000) -n Number of core dumps to write before exiting (default is 1) -s Consecutive seconds before dump is written (default is 10) + -o Path and/or filename prefix where the core dump is written to -d Writes diagnostic logs to syslog TARGET must be exactly one of these: -p pid of the process @@ -87,7 +89,18 @@ ``` sudo procdump -C 65 -M 100 -p 1234 ``` - +The following will create a core dump in the `/tmp` directory immediately. +``` +sudo procdump -o /tmp -p 1234 +``` +The following will create a core dump in the current directory with the name dump_0.1234. If -n is used, the files will be named dump_0.1234, dump_1.1234 and so on. +``` +sudo procdump -o dump -p 1234 +``` +The following will create a core dump when a SIGSEGV occurs. +``` +sudo procdump -G 11 -p 1234 +``` > All options can also be used with -w instead of -p. -w will wait for a > process with the given name. The following waits for a process named `my_application` and creates a core dump immediately when it is found. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/dist/procdump.spec.in new/ProcDump-for-Linux-1.2/dist/procdump.spec.in --- old/ProcDump-for-Linux-1.1.1/dist/procdump.spec.in 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/dist/procdump.spec.in 2021-09-15 00:53:53.000000000 +0200 @@ -54,6 +54,11 @@ %changelog +* Tue Sep 14 2021 Javid Habibi <jahab...@microsoft.com> - 1.2 +- added signal trigger +- added custom filepath for memory dump generation +- various small bug fixes + * Fri Apr 3 2020 Javid Habibi <jahab...@microsoft.com> - 1.1.1 - implimented thread and file descriptor count trigger - added polling interval switch diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/include/CoreDumpWriter.h new/ProcDump-for-Linux-1.2/include/CoreDumpWriter.h --- old/ProcDump-for-Linux-1.1.1/include/CoreDumpWriter.h 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/include/CoreDumpWriter.h 2021-09-15 00:53:53.000000000 +0200 @@ -59,6 +59,7 @@ CPU, // trigger on CPU threshold THREAD, // trigger on thread count FILEDESC, // trigger on file descriptor count + SIGNAL, // trigger on signal TIME, // trigger on time interval MANUAL // manual trigger }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/include/Logging.h new/ProcDump-for-Linux-1.2/include/Logging.h --- old/ProcDump-for-Linux-1.1.1/include/Logging.h 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/include/Logging.h 2021-09-15 00:53:53.000000000 +0200 @@ -19,16 +19,13 @@ #include <stdarg.h> #include <time.h> -#define INTERNAL_ERROR "Internal Error has occurred. If problem continues to occur run procudmp with -d flag to trace issue" +#define INTERNAL_ERROR "Internal Error has occurred. If problem continues to occur run procdump with -d flag to trace issue" // double-macro-stringify to expand __FILE__ and __LINE__ properly when they are injected in files #define S1(x) #x #define S2(x) S1(x) #define LOCATION "in "__FILE__ ", at line " S2(__LINE__) -extern struct ProcDumpConfiguration g_config; - - enum LogLevel{ debug, info, // standard output @@ -39,7 +36,6 @@ void Log(enum LogLevel logLevel, const char *message, ...); -pthread_mutex_t LoggerLock; void DiagTrace(const char* message, ...); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/include/ProcDumpConfiguration.h new/ProcDump-for-Linux-1.2/include/ProcDumpConfiguration.h --- old/ProcDump-for-Linux-1.1.1/include/ProcDumpConfiguration.h 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/include/ProcDumpConfiguration.h 2021-09-15 00:53:53.000000000 +0200 @@ -25,6 +25,10 @@ #include <limits.h> #include <dirent.h> #include <errno.h> +#include <libgen.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include "Handle.h" #include "TriggerThreadProcs.h" @@ -40,11 +44,6 @@ #define MIN_POLLING_INTERVAL 1000 // default trigger polling interval (ms) -struct ProcDumpConfiguration g_config; // backbone of the program - -long HZ; // clock ticks per second -int MAXIMUM_CPU; // maximum cpu usage percentage (# cores * 100) - // ------------------- // Structs // ------------------- @@ -82,7 +81,10 @@ bool DiagnosticsLoggingEnabled; // -d int ThreadThreshold; // -T int FileDescriptorThreshold; // -F + int SignalNumber; // -G int PollingInterval; // -I + char *CoreDumpPath; // -o + char *CoreDumpName; // -o // multithreading // set max number of concurrent dumps on init (default to 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/include/TriggerThreadProcs.h new/ProcDump-for-Linux-1.2/include/TriggerThreadProcs.h --- old/ProcDump-for-Linux-1.1.1/include/TriggerThreadProcs.h 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/include/TriggerThreadProcs.h 2021-09-15 00:53:53.000000000 +0200 @@ -19,6 +19,7 @@ #include <memory.h> #include <zconf.h> #include <sys/sysinfo.h> +#include <sys/ptrace.h> #include <unistd.h> #include "CoreDumpWriter.h" @@ -32,6 +33,7 @@ void *CpuMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); void *ThreadCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); void *FileDescriptorCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); +void *SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); void *TimerThread(void *thread_args /* struct ProcDumpConfiguration* */); #endif // TRIGGER_THREAD_PROCS_H \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/procdump.1 new/ProcDump-for-Linux-1.2/procdump.1 --- old/ProcDump-for-Linux-1.1.1/procdump.1 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/procdump.1 2021-09-15 00:53:53.000000000 +0200 @@ -1,5 +1,5 @@ .\" Manpage for procdump. -.TH man 8 "12/09/2019" "1.1.1" "procdump manpage" +.TH man 8 "04/03/2020" "1.2" "procdump manpage" .SH NAME procdump \- generate coredumps based off performance triggers. .SH SYNOPSIS @@ -14,6 +14,7 @@ -I Polling frequency in milliseconds (default is 1000) -n Number of core dumps to write before exiting (default is 1) -s Consecutive seconds before dump is written (default is 10) + -o Path and/or filename prefix where the core dump is written to -d Writes diagnostic logs to syslog TARGET must be exactly one of these: -p pid of the process diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/src/CoreDumpWriter.c new/ProcDump-for-Linux-1.2/src/CoreDumpWriter.c --- old/ProcDump-for-Linux-1.1.1/src/CoreDumpWriter.c 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/src/CoreDumpWriter.c 2021-09-15 00:53:53.000000000 +0200 @@ -12,7 +12,7 @@ char *sanitize(char *processName); -static const char *CoreDumpTypeStrings[] = { "commit", "cpu", "thread", "filedesc", "time", "manual" }; +static const char *CoreDumpTypeStrings[] = { "commit", "cpu", "thread", "filedesc", "signal", "time", "manual" }; bool GenerateCoreClrDump(char* socketName, char* dumpFileName); bool IsCoreClrProcess(struct CoreDumpWriter *self, char** socketName); @@ -406,6 +406,7 @@ char command[BUFFER_LENGTH]; char ** outputBuffer; char lineBuffer[BUFFER_LENGTH]; + char gcorePrefixName[BUFFER_LENGTH]; char coreDumpFileName[BUFFER_LENGTH]; int lineLength; int i; @@ -437,26 +438,53 @@ } strftime(date, 26, "%Y-%m-%d_%H:%M:%S", timerInfo); + // assemble the full file name (including path) for core dumps + if(self->Config->CoreDumpName != NULL) { + if(snprintf(gcorePrefixName, BUFFER_LENGTH, "%s/%s_%d", + self->Config->CoreDumpPath, + self->Config->CoreDumpName, + self->Config->NumberOfDumpsCollected) < 0) { + Log(error, INTERNAL_ERROR); + Trace("WriteCoreDumpInternal: failed sprintf custom output file name"); + exit(-1); + } + } else { + if(snprintf(gcorePrefixName, BUFFER_LENGTH, "%s/%s_%s_%s", + self->Config->CoreDumpPath, name, desc, date) < 0) { + Log(error, INTERNAL_ERROR); + Trace("WriteCoreDumpInternal: failed sprintf default output file name"); + exit(-1); + } + } + // assemble the command - if(sprintf(command, "gcore -o %s_%s_%s %d 2>&1", name, desc, date, pid) < 0){ + if(snprintf(command, BUFFER_LENGTH, "gcore -o %s %d 2>&1", gcorePrefixName, pid) < 0){ Log(error, INTERNAL_ERROR); Trace("WriteCoreDumpInternal: failed sprintf gcore command"); exit(-1); } // assemble filename - if(sprintf(coreDumpFileName, "%s_%s_%s.%d", name, desc, date, pid) < 0){ + if(snprintf(coreDumpFileName, BUFFER_LENGTH, "%s.%d", gcorePrefixName, pid) < 0){ Log(error, INTERNAL_ERROR); Trace("WriteCoreDumpInternal: failed sprintf core file name"); exit(-1); } + // check if we're allowed to write into the target directory + if(access(self->Config->CoreDumpPath, W_OK) < 0) { + Log(error, INTERNAL_ERROR); + Trace("WriteCoreDumpInternal: no write permission to core dump target file %s", + coreDumpFileName); + exit(-1); + } + if(socketName!=NULL) { // If we have a socket name, we're dumping a .NET Core 3+ process.... if(GenerateCoreClrDump(socketName, coreDumpFileName)==false) { - Log(error, "An error occured while generating the core dump for .NET 3.x+ process"); + Log(error, "An error occurred while generating the core dump for .NET 3.x+ process"); } else { @@ -480,7 +508,7 @@ self->Config->gcorePid = gcorePid; if(commandPipe == NULL){ - Log(error, "An error occured while generating the core dump"); + Log(error, "An error occurred while generating the core dump"); Trace("WriteCoreDumpInternal: Failed to open pipe to gcore"); exit(1); } @@ -507,7 +535,7 @@ // check if gcore was able to generate the dump if(strstr(outputBuffer[i-1], "gcore: failed") != NULL){ - Log(error, "An error occured while generating the core dump"); + Log(error, "An error occurred while generating the core dump"); // log gcore message for(int j = 0; j < i; j++){ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/src/Events.c new/ProcDump-for-Linux-1.2/src/Events.c --- old/ProcDump-for-Linux-1.1.1/src/Events.c 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/src/Events.c 2021-09-15 00:53:53.000000000 +0200 @@ -81,7 +81,7 @@ Event->nWaiters = 0; if (Name == NULL) { - sprintf(Event->Name, "Unamed Event %d", ++unamedEventId); + sprintf(Event->Name, "Unnamed Event %d", ++unamedEventId); } else if (strlen(Name) >= MAX_EVENT_NAME) { strncpy(Event->Name, Name, MAX_EVENT_NAME); Event->Name[MAX_EVENT_NAME - 1] = '\0'; // null terminate diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/src/Logging.c new/ProcDump-for-Linux-1.2/src/Logging.c --- old/ProcDump-for-Linux-1.1.1/src/Logging.c 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/src/Logging.c 2021-09-15 00:53:53.000000000 +0200 @@ -11,6 +11,8 @@ #include "ProcDumpConfiguration.h" static const char *LogLevelStrings[] = { "DEBUG", "INFO", "WARN", "CRITICAL", "ERROR" }; +extern struct ProcDumpConfiguration g_config; +pthread_mutex_t LoggerLock; void LogFormatter(enum LogLevel logLevel, const char *message, va_list args) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/src/ProcDumpConfiguration.c new/ProcDump-for-Linux-1.2/src/ProcDumpConfiguration.c --- old/ProcDump-for-Linux-1.1.1/src/ProcDumpConfiguration.c 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/src/ProcDumpConfiguration.c 2021-09-15 00:53:53.000000000 +0200 @@ -14,15 +14,21 @@ static sigset_t sig_set; static pthread_t sig_thread_id; +static pthread_t sig_monitor_thread_id; +extern pthread_mutex_t LoggerLock; +long HZ; // clock ticks per second +int MAXIMUM_CPU; // maximum cpu usage percentage (# cores * 100) +struct ProcDumpConfiguration g_config; // backbone of the program +pthread_mutex_t ptrace_mutex; //-------------------------------------------------------------------- // -// SignalThread - Thread for hanlding graceful Async signals (e.g., SIGINT, SIGTERM) +// SignalThread - Thread for handling graceful Async signals (e.g., SIGINT, SIGTERM) // //-------------------------------------------------------------------- void *SignalThread(void *input) { - struct ProcDumpConfiguration *self = (struct ProcDumpConfiguration *)input; + struct ProcDumpConfiguration *config = (struct ProcDumpConfiguration *)input; int sig_caught, rc; if ((rc = sigwait(&sig_set, &sig_caught)) != 0) { @@ -33,13 +39,31 @@ switch (sig_caught) { case SIGINT: - SetQuit(self, 1); - if(self->gcorePid != NO_PID) { + SetQuit(config, 1); + if(config->gcorePid != NO_PID) { Log(info, "Shutting down gcore"); - if((rc = kill(-self->gcorePid, SIGKILL)) != 0) { // pass negative PID to kill entire PGRP with value of gcore PID + if((rc = kill(-config->gcorePid, SIGKILL)) != 0) { // pass negative PID to kill entire PGRP with value of gcore PID Log(error, "Failed to shutdown gcore."); } } + + // Need to make sure we detach from ptrace (if not attached it will silently fail) + // To avoid situations where we have intercepted a signal and CTRL-C is hit, we synchronize + // access to the signal path (in SignalMonitoringThread). Note, there is still a race but + // acceptable since it is very unlikely to occur. We also cancel the SignalMonitorThread to + // break it out of waitpid call. + if(config->SignalNumber != -1) + { + pthread_mutex_lock(&ptrace_mutex); + ptrace(PTRACE_DETACH, config->ProcessId, 0, 0); + pthread_mutex_unlock(&ptrace_mutex); + + if ((rc = pthread_cancel(sig_monitor_thread_id)) != 0) { + Log(error, "An error occurred while canceling SignalMonitorThread.\n"); + exit(-1); + } + } + Log(info, "Quit"); break; default: @@ -65,6 +89,7 @@ } InitProcDumpConfiguration(&g_config); pthread_mutex_init(&LoggerLock, NULL); + pthread_mutex_init(&ptrace_mutex, NULL); } //-------------------------------------------------------------------- @@ -124,6 +149,7 @@ self->MemoryThreshold = -1; self->ThreadThreshold = -1; self->FileDescriptorThreshold = -1; + self->SignalNumber = -1; self->ThresholdSeconds = DEFAULT_DELTA_TIME; self->bCpuTriggerBelowValue = false; self->bMemoryTriggerBelowValue = false; @@ -132,6 +158,8 @@ self->DiagnosticsLoggingEnabled = false; self->gcorePid = NO_PID; self->PollingInterval = MIN_POLLING_INTERVAL; + self->CoreDumpPath = NULL; + self->CoreDumpName = NULL; SetEvent(&g_evtConfigurationInitialized.event); // We've initialized and are now re-entrant safe } @@ -157,6 +185,9 @@ // The string constant is not on the heap. free(self->ProcessName); } + + free(self->CoreDumpPath); + free(self->CoreDumpName); } //-------------------------------------------------------------------- @@ -180,7 +211,7 @@ // parse arguments int next_option; int option_index = 0; - const char* short_options = "+p:C:c:M:m:n:s:w:T:F:I:dh"; + const char* short_options = "+p:C:c:M:m:n:s:w:T:F:G:I:o:dh"; const struct option long_options[] = { { "pid", required_argument, NULL, 'p' }, { "cpu", required_argument, NULL, 'C' }, @@ -190,13 +221,19 @@ { "number-of-dumps", required_argument, NULL, 'n' }, { "time-between-dumps", required_argument, NULL, 's' }, { "wait", required_argument, NULL, 'w' }, - { "threads", required_argument, NULL, 'T' }, - { "filedescriptors", required_argument, NULL, 'F' }, + { "threads", required_argument, NULL, 'T' }, + { "filedescriptors", required_argument, NULL, 'F' }, + { "signal", required_argument, NULL, 'G' }, { "pollinginterval", required_argument, NULL, 'I' }, + { "output-path", required_argument, NULL, 'o' }, { "diag", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' } + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } }; + char *tempOutputPath = NULL; + struct stat statbuf; + // start parsing command line arguments while ((next_option = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) { switch (next_option) { @@ -239,6 +276,14 @@ } break; + case 'G': + if (self->SignalNumber != -1 || !IsValidNumberArg(optarg) || + (self->SignalNumber = atoi(optarg)) < 0 ) { + Log(error, "Invalid signal specified."); + return PrintUsage(self); + } + break; + case 'c': if (self->CpuThreshold != -1 || !IsValidNumberArg(optarg) || (self->CpuThreshold = atoi(optarg)) < 0 || self->CpuThreshold > MAXIMUM_CPU) { @@ -288,10 +333,36 @@ self->ProcessName = strdup(optarg); break; + case 'o': + tempOutputPath = strdup(optarg); + + // Check if the user provided an existing directory or a path + // ending in a '/'. In this case, use the default naming + // convention but place the files in the given directory. + if ((stat(tempOutputPath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) || + tempOutputPath[strlen(tempOutputPath)-1] == '/') { + self->CoreDumpPath = tempOutputPath; + self->CoreDumpName = NULL; + } else { + self->CoreDumpPath = strdup(dirname(tempOutputPath)); + free(tempOutputPath); + tempOutputPath = strdup(optarg); + self->CoreDumpName = strdup(basename(tempOutputPath)); + free(tempOutputPath); + } + + // Check if the path portion of the output format is valid + if (stat(self->CoreDumpPath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) { + Log(error, "Invalid directory (\"%s\") provided for core dump output.", + self->CoreDumpPath); + return PrintUsage(self); + } + break; + case 'd': self->DiagnosticsLoggingEnabled = true; break; - + case 'h': return PrintUsage(self); @@ -301,8 +372,12 @@ } } - // Check for multi-arg situations + // If no path was provided, assume the current directory + if (self->CoreDumpPath == NULL) { + self->CoreDumpPath = strdup("."); + } + // Check for multi-arg situations // if number of dumps is set, but no thresholds, just go on timer if (self->NumberOfDumpsToCollect != -1 && self->MemoryThreshold == -1 && @@ -312,6 +387,31 @@ self->bTimerThreshold = true; } + + // If signal dump is specified, it can be the only trigger that is used. + // Otherwise we might run into a situation where the other triggers invoke + // gcore while the target is being ptraced due to signal trigger. + // Interval has no meaning during signal monitoring. + // + if(self->SignalNumber != -1) + { + if(self->CpuThreshold != -1 || self->ThreadThreshold != -1 || self->FileDescriptorThreshold != -1 || self->MemoryThreshold != -1) + { + Log(error, "Signal trigger must be the only trigger specified."); + return PrintUsage(self); + } + if(self->PollingInterval != MIN_POLLING_INTERVAL) + { + Log(error, "Polling interval has no meaning during signal monitoring."); + return PrintUsage(self); + } + + // Again, we cant have another trigger (in this case timer) kicking off another dump generation since we will already + // be attached via ptrace. + self->bTimerThreshold = false; + } + + if(self->ProcessId == NO_PID && !self->WaitingForProcessName){ Log(error, "A valid PID or process name must be specified"); return PrintUsage(self); @@ -544,6 +644,13 @@ } } + if (self->SignalNumber != -1) { + if ((rc = pthread_create(&sig_monitor_thread_id, NULL, SignalMonitoringThread, (void *)self)) != 0) { + Trace("CreateTriggerThreads: failed to create SignalMonitoringThread."); + return rc; + } + } + if (self->bTimerThreshold) { if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, TimerThread, (void *)self)) != 0) { Trace("CreateTriggerThreads: failed to create TimerThread."); @@ -631,20 +738,38 @@ int WaitForAllThreadsToTerminate(struct ProcDumpConfiguration *self) { int rc = 0; - for (int i = 0; i < self->nThreads; i++) { - if ((rc = pthread_join(self->Threads[i], NULL)) != 0) { - Log(error, "An error occured while joining threads\n"); + + + // Wait for the signal monitoring thread if there is one. If there is one, it will be the only + // one. + if(self->SignalNumber != -1) + { + if ((rc = pthread_join(sig_monitor_thread_id, NULL)) != 0) { + Log(error, "An error occurred while joining SignalMonitorThread.\n"); exit(-1); } } - if ((rc = pthread_cancel(sig_thread_id)) != 0) { - Log(error, "An error occured while canceling SignalThread.\n"); - exit(-1); + else + { + // Wait for the other monitoring threads + for (int i = 0; i < self->nThreads; i++) { + if ((rc = pthread_join(self->Threads[i], NULL)) != 0) { + Log(error, "An error occurred while joining threads\n"); + exit(-1); + } + } } + + // Cancel the signal handling thread. + // We dont care about the return since the signal thread might already be gone. + pthread_cancel(sig_thread_id); + + // Wait for signal handling thread to complete if ((rc = pthread_join(sig_thread_id, NULL)) != 0) { - Log(error, "An error occured while joining SignalThread.\n"); + Log(error, "An error occurred while joining SignalThread.\n"); exit(-1); } + return rc; } @@ -681,6 +806,10 @@ bool PrintConfiguration(struct ProcDumpConfiguration *self) { if (WaitForSingleObject(&self->evtConfigurationPrinted,0) == WAIT_TIMEOUT) { + if(self->SignalNumber != -1) + { + printf("** NOTE ** Signal triggers use PTRACE which will impact the performance of the target process\n\n"); + } printf("Process:\t\t%s", self->ProcessName); if (!self->WaitingForProcessName) { printf(" (%d)", self->ProcessId); @@ -715,11 +844,25 @@ if (self->ThreadThreshold != -1) { printf("Thread Threshold:\t>=%d\n", self->ThreadThreshold); } + else { + printf("Thread Threshold:\t\tn/a\n"); + } // File descriptor if (self->FileDescriptorThreshold != -1) { printf("File descriptor Threshold:\t>=%d\n", self->FileDescriptorThreshold); } + else { + printf("File descriptor Threshold:\t\tn/a\n"); + } + + // Signal + if (self->SignalNumber != -1) { + printf("Signal number:\t%d\n", self->SignalNumber); + } + else { + printf("Signal:\t\tn/a\n"); + } // Polling inverval printf("Polling interval (ms):\t%d\n", self->PollingInterval); @@ -730,6 +873,12 @@ // number of dumps and others printf("Number of Dumps:\t%d\n", self->NumberOfDumpsToCollect); + // Output directory and filename + printf("Output directory for core dumps:\t%s\n", self->CoreDumpPath); + if (self->CoreDumpName != NULL) { + printf("Custom name for core dumps:\t%s_<counter>.<pid>\n", self->CoreDumpName); + } + SetEvent(&self->evtConfigurationPrinted.event); return true; } @@ -833,11 +982,11 @@ //-------------------------------------------------------------------- void PrintBanner() { - printf("\nProcDump v1.1.1 - Sysinternals process dump utility\n"); - printf("Copyright (C) 2019 Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n"); + printf("\nProcDump v1.2 - Sysinternals process dump utility\n"); + printf("Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n"); printf("Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi\n"); - printf("Monitors a process and writes a dump file when the process exceeds the\n"); + printf("Monitors a process and writes a dump file when the process meets the\n"); printf("specified criteria.\n\n"); } @@ -857,10 +1006,12 @@ printf(" -M Trigger core dump generation when memory commit exceeds or equals specified value (MB)\n"); printf(" -m Trigger core dump generation when when memory commit is less than specified value (MB)\n"); printf(" -T Trigger when thread count exceeds or equals specified value.\n"); - printf(" -F Trigger when filedescriptor count exceeds or equals specified value.\n"); + printf(" -F Trigger when file descriptor count exceeds or equals specified value.\n"); + printf(" -G Trigger when signal with the specified value (num) is sent (uses PTRACE and will affect performance of target process).\n"); printf(" -I Polling frequency in milliseconds (default is %d)\n", MIN_POLLING_INTERVAL); printf(" -n Number of core dumps to write before exiting (default is %d)\n", DEFAULT_NUMBER_OF_DUMPS); printf(" -s Consecutive seconds before dump is written (default is %d)\n", DEFAULT_DELTA_TIME); + printf(" -o Path and/or filename prefix where the core dump is written to\n"); printf(" -d Writes diagnostic logs to syslog\n"); printf(" TARGET must be exactly one of these:\n"); printf(" -p pid of the process\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/src/Procdump.c new/ProcDump-for-Linux-1.2/src/Procdump.c --- old/ProcDump-for-Linux-1.1.1/src/Procdump.c 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/src/Procdump.c 2021-09-15 00:53:53.000000000 +0200 @@ -9,6 +9,7 @@ //-------------------------------------------------------------------- #include "Procdump.h" +extern struct ProcDumpConfiguration g_config; int main(int argc, char *argv[]) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/src/TriggerThreadProcs.c new/ProcDump-for-Linux-1.2/src/TriggerThreadProcs.c --- old/ProcDump-for-Linux-1.1.1/src/TriggerThreadProcs.c 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/src/TriggerThreadProcs.c 2021-09-15 00:53:53.000000000 +0200 @@ -8,6 +8,8 @@ //-------------------------------------------------------------------- #include "TriggerThreadProcs.h" +extern long HZ; // clock ticks per second +extern pthread_mutex_t ptrace_mutex; void *CommitMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) { @@ -47,7 +49,7 @@ } else { - Log(error, "An error occured while parsing procfs\n"); + Log(error, "An error occurred while parsing procfs\n"); exit(-1); } } @@ -86,7 +88,7 @@ } else { - Log(error, "An error occured while parsing procfs\n"); + Log(error, "An error occurred while parsing procfs\n"); exit(-1); } } @@ -126,7 +128,7 @@ } else { - Log(error, "An error occured while parsing procfs\n"); + Log(error, "An error occurred while parsing procfs\n"); exit(-1); } } @@ -137,6 +139,100 @@ pthread_exit(NULL); } +// +// This thread monitors for a specific signal to be sent to target process. +// It uses ptrace (PTRACE_SEIZE) and once the signal with the corresponding +// signal number is intercepted, it detaches from the target process in a stopped state +// followed by invoking gcore to generate the dump. Once completed, a SIGCONT followed by the +// original signal is sent to the target process. Signals of non-interest are simply forwarded +// to the target process. +// +// Polling interval has no meaning during signal monitoring. +// +void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) +{ + Trace("SignalMonitoringThread: Starting SignalMonitoring Thread"); + struct ProcDumpConfiguration *config = (struct ProcDumpConfiguration *)thread_args; + int wstatus; + int signum=-1; + int rc = 0; + struct CoreDumpWriter *writer = NewCoreDumpWriter(SIGNAL, config); + + if ((rc = WaitForQuitOrEvent(config, &config->evtStartMonitoring, INFINITE_WAIT)) == WAIT_OBJECT_0 + 1) + { + // Attach to the target process. We use SEIZE here to avoid + // the SIGSTOP issues of the ATTACH method. + if (ptrace(PTRACE_SEIZE, config->ProcessId, NULL, NULL) == -1) + { + Log(error, "Unable to PTRACE the target process"); + } + else + { + while(1) + { + // Wait for signal to be delivered + waitpid(config->ProcessId, &wstatus, 0); + if(WIFEXITED(wstatus) || WIFSIGNALED(wstatus)) + { + ptrace(PTRACE_DETACH, config->ProcessId, 0, 0); + break; + } + + pthread_mutex_lock(&ptrace_mutex); + + // We are now in a signal-stop state + + signum = WSTOPSIG(wstatus); + if(signum == config->SignalNumber) + { + // We have to detach in a STOP state so we can invoke gcore + if(ptrace(PTRACE_DETACH, config->ProcessId, 0, SIGSTOP) == -1) + { + Log(error, "Unable to PTRACE (DETACH) the target process"); + pthread_mutex_unlock(&ptrace_mutex); + break; + } + + // Write core dump + Log(info, "Signal intercepted: %d", signum); + rc = WriteCoreDump(writer); + + kill(config->ProcessId, SIGCONT); + + if(config->NumberOfDumpsCollected >= config->NumberOfDumpsToCollect) + { + // If we are over the max number of dumps to collect, send the original signal we intercepted. + kill(config->ProcessId, signum); + pthread_mutex_unlock(&ptrace_mutex); + break; + } + + ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); + + // Re-attach to the target process + if (ptrace(PTRACE_SEIZE, config->ProcessId, NULL, NULL) == -1) + { + Log(error, "Unable to PTRACE the target process"); + pthread_mutex_unlock(&ptrace_mutex); + break; + } + + pthread_mutex_unlock(&ptrace_mutex); + continue; + } + + // Resume execution of the target process + ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); + pthread_mutex_unlock(&ptrace_mutex); + } + } + } + + free(writer); + Trace("SignalMonitoringThread: Exiting SignalMonitoring Thread"); + pthread_exit(NULL); +} + void *CpuMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) { Trace("CpuMonitoringThread: Starting Trigger Thread"); @@ -179,7 +275,7 @@ } else { - Log(error, "An error occured while parsing procfs\n"); + Log(error, "An error occurred while parsing procfs\n"); exit(-1); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/runProcDumpAndValidate.sh new/ProcDump-for-Linux-1.2/tests/integration/runProcDumpAndValidate.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/runProcDumpAndValidate.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/runProcDumpAndValidate.sh 2021-09-15 00:53:53.000000000 +0200 @@ -6,6 +6,11 @@ dumpDir=$(mktemp -d -t dump_XXXXXX) cd $dumpDir + dumpParam="" + if [ "$#" -ge "6" -a -n "$6" ]; then + dumpParam="-o $dumpDir/$6" + fi + if [ -z "$TESTPROGNAME" ]; then if [ "$5" == "MEM" ]; then stress-ng --vm 1 --vm-hang 0 --vm-bytes $1 --timeout 20s -q& @@ -17,22 +22,22 @@ sleep 1s - childrenpid=$(pidof -o $pid stress-ng) + childrenpid=$(pidof -o $pid $(which stress-ng)) echo "ChildrenPID: $childrenpid" childpid=$(echo $childrenpid | cut -d " " -f1) echo "ChildPID: $childpid" - echo "$PROCDUMPPATH $2 $3 -p $childpid" - $PROCDUMPPATH $2 $3 -p $childpid + echo "$PROCDUMPPATH $2 $3 $dumpParam -p $childpid" + $PROCDUMPPATH $2 $3 $dumpParam -p $childpid else TESTPROGPATH=$(readlink -m "$DIR/../../bin/$TESTPROGNAME"); (sleep 2; $TESTPROGPATH "$TESTPROGMODE") & pid=$! echo "PID: $pid" - echo "$PROCDUMPPATH $2 $3 -w $TESTPROGNAME" - $PROCDUMPPATH $2 $3 -w "$TESTPROGNAME" + echo "$PROCDUMPPATH $2 $3 $dumpParam -w $TESTPROGNAME" + $PROCDUMPPATH $2 $3 $dumpParam -w "$TESTPROGNAME" fi if ps -p $pid > /dev/null diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger=80 shouldDump=true -runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_by_name.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_by_name.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_by_name.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_by_name.sh 2021-09-15 00:53:53.000000000 +0200 @@ -11,4 +11,4 @@ procDumpTrigger=50 shouldDump=true -runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_custom_core_file_name.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_custom_core_file_name.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_custom_core_file_name.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_custom_core_file_name.sh 2021-09-15 00:53:53.000000000 +0200 @@ -0,0 +1,12 @@ +#!/bin/bash +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; +runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); +source $runProcDumpAndValidate + +stressPercentage=90 +procDumpType="-C" +procDumpTrigger=80 +shouldDump=true +customDumpFileName="custom_dump_file" + +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" $customDumpFileName diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_nonexisting_output_directory.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_nonexisting_output_directory.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_nonexisting_output_directory.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_nonexisting_output_directory.sh 2021-09-15 00:53:53.000000000 +0200 @@ -0,0 +1,12 @@ +#!/bin/bash +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; +runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); +source $runProcDumpAndValidate + +stressPercentage=90 +procDumpType="-C" +procDumpTrigger=80 +shouldDump=false +customDumpFileName="missing_subdir/custom_dump_file" + +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" $customDumpFileName diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_notdump.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_notdump.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_notdump.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_notdump.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger=80 shouldDump=false -runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_trigger_cpu_memory.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_trigger_cpu_memory.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/high_cpu_trigger_cpu_memory.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/high_cpu_trigger_cpu_memory.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger=80 shouldDump=true -runProcDumpAndValidate $stressPercentage "$procDumpType" $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage "$procDumpType" $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger=20 shouldDump=true -runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu_by_name.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu_by_name.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu_by_name.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu_by_name.sh 2021-09-15 00:53:53.000000000 +0200 @@ -10,4 +10,4 @@ procDumpTrigger=20 shouldDump=true -runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu_notdump.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu_notdump.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu_notdump.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu_notdump.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger=20 shouldDump=false -runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage $procDumpType $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu_trigger_cpu_memory.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu_trigger_cpu_memory.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/low_cpu_trigger_cpu_memory.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/low_cpu_trigger_cpu_memory.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger=20 shouldDump=true -runProcDumpAndValidate $stressPercentage "$procDumpType" $procDumpTrigger $shouldDump +runProcDumpAndValidate $stressPercentage "$procDumpType" $procDumpTrigger $shouldDump "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/ondemand.sh new/ProcDump-for-Linux-1.2/tests/integration/scenarios/ondemand.sh --- old/ProcDump-for-Linux-1.1.1/tests/integration/scenarios/ondemand.sh 2020-04-03 21:03:02.000000000 +0200 +++ new/ProcDump-for-Linux-1.2/tests/integration/scenarios/ondemand.sh 2021-09-15 00:53:53.000000000 +0200 @@ -8,4 +8,4 @@ procDumpTrigger="" shouldDump=true -runProcDumpAndValidate "$stressPercentage" "$procDumpType" "$procDumpTrigger" "$shouldDump" +runProcDumpAndValidate "$stressPercentage" "$procDumpType" "$procDumpTrigger" "$shouldDump" "CPU" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/signal/makefile new/ProcDump-for-Linux-1.2/tests/integration/signal/makefile --- old/ProcDump-for-Linux-1.1.1/tests/integration/signal/makefile 1970-01-01 01:00:00.000000000 +0100 +++ new/ProcDump-for-Linux-1.2/tests/integration/signal/makefile 2021-09-15 00:53:53.000000000 +0200 @@ -0,0 +1,2 @@ +signaltest: signaltest.c + gcc -o signaltest signaltest.c -I. Binary files old/ProcDump-for-Linux-1.1.1/tests/integration/signal/signaltest and new/ProcDump-for-Linux-1.2/tests/integration/signal/signaltest differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1.1/tests/integration/signal/signaltest.c new/ProcDump-for-Linux-1.2/tests/integration/signal/signaltest.c --- old/ProcDump-for-Linux-1.1.1/tests/integration/signal/signaltest.c 1970-01-01 01:00:00.000000000 +0100 +++ new/ProcDump-for-Linux-1.2/tests/integration/signal/signaltest.c 2021-09-15 00:53:53.000000000 +0200 @@ -0,0 +1,41 @@ +// +// Used to test the signal triggering (and forwarding) of procdump. +// +// 1. Run this test app (it registers for the first 23 signals). +// 2. Run procdump against this pid +// 3. use kill to send whichever signal you are interested in triggering procdump (or not trigger) +// 4. Make sure in all cases (except for signals that can't be intercepted) that this program outputs "Caught signal X" +// where X is the signal you sent. If the output does not show that signal being handled, it means the signal forwarding +// in procdump is not working properly and needs to be investigated. +// +#include <stdio.h> +#include <stdlib.h> +#include <wait.h> +#include <sys/ptrace.h> +#include <sys/types.h> +#include <unistd.h> + + +void sig_handler(int signum) +{ + if(signum==SIGINT) + { + exit(-1); + } + + // We shouldnt be using printf in a signal handler but in this simple test case its fine + printf("Caught signal: %d\n", signum); +} + +void main(int argc, char** argv) +{ + for(int i=0; i<24; i++) + { + signal(i, sig_handler); + } + + while(1) + { + pause(); + } +} \ No newline at end of file