Hello community, here is the log from the commit of package procdump for openSUSE:Factory checked in at 2020-06-07 21:39:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/procdump (Old) and /work/SRC/openSUSE:Factory/.procdump.new.3606 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "procdump" Sun Jun 7 21:39:21 2020 rev:4 rq:812186 version:1.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/procdump/procdump.changes 2020-01-30 16:20:13.066068324 +0100 +++ /work/SRC/openSUSE:Factory/.procdump.new.3606/procdump.changes 2020-06-07 21:39:28.953671532 +0200 @@ -1,0 +2,8 @@ +Sun Jun 7 08:08:00 UTC 2020 - Luigi Baldoni <aloi...@gmx.com> + +- Update to version 1.1.1 + * Added -T thread count trigger and -F file descriptor count + trigger +- Add procdump-gcc10.patch + +------------------------------------------------------------------- Old: ---- procdump-1.1.tar.gz New: ---- procdump-1.1.1.tar.gz procdump-gcc10.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ procdump.spec ++++++ --- /var/tmp/diff_new_pack.Rr3s3U/_old 2020-06-07 21:39:29.725673980 +0200 +++ /var/tmp/diff_new_pack.Rr3s3U/_new 2020-06-07 21:39:29.729673992 +0200 @@ -17,12 +17,14 @@ Name: procdump -Version: 1.1 +Version: 1.1.1 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 @@ -30,7 +32,7 @@ suite. It can create core dumps of processes based on performance triggers. %prep -%setup -q -n ProcDump-for-Linux-%{version} +%autosetup -p1 -n ProcDump-for-Linux-%{version} %build export CFLAGS="%{optflags}" ++++++ procdump-1.1.tar.gz -> procdump-1.1.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/INSTALL.md new/ProcDump-for-Linux-1.1.1/INSTALL.md --- old/ProcDump-for-Linux-1.1/INSTALL.md 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/INSTALL.md 2020-04-03 21:03:02.000000000 +0200 @@ -1,6 +1,6 @@ # Install ProcDump -## Ubuntu 14.04, 16.04, 18.04, 19.04 & 19.10 +## Ubuntu 16.04, 18.04 & 19.10 #### 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 @@ -71,6 +71,18 @@ ``` #### 2. Install Procdump +```sh +sudo dnf install procdump +``` + +## 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/31/prod.repo +``` + +#### 2. Install Procdump ```sh sudo dnf install procdump ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/Makefile new/ProcDump-for-Linux-1.1.1/Makefile --- old/ProcDump-for-Linux-1.1/Makefile 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/Makefile 2020-04-03 21:03:02.000000000 +0200 @@ -16,6 +16,8 @@ OUT=$(BINDIR)/procdump TESTOUT=$(BINDIR)/ProcDumpTestApplication +# Revision value from build pipeline +REVISION:=$(if $(REVISION),$(REVISION),'99999') # installation directory DESTDIR ?= / @@ -33,7 +35,7 @@ $(BUILDDIR)/SOURCES $(BUILDDIR)/SPECS $(BUILDDIR)/BUILD $(BUILDDIR)/BUILDROOT # package details -PKG_VERSION=1.1 +PKG_VERSION=1.1.1 all: clean build @@ -82,8 +84,8 @@ .PHONY: deb deb: tarball - debbuild --define='_Revision ${Revision}' $(PKGBUILDFLAGS) $(BUILDDIR)/SPECS/procdump.spec + debbuild --define='_Revision ${REVISION}' $(PKGBUILDFLAGS) $(BUILDDIR)/SPECS/procdump.spec .PHONY: rpm rpm: tarball - rpmbuild --define='_Revision ${Revision}' $(PKGBUILDFLAGS) $(BUILDDIR)/SPECS/procdump.spec + rpmbuild --define='_Revision ${REVISION}' $(PKGBUILDFLAGS) $(BUILDDIR)/SPECS/procdump.spec diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/README.md new/ProcDump-for-Linux-1.1.1/README.md --- old/ProcDump-for-Linux-1.1/README.md 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/README.md 2020-04-03 21:03:02.000000000 +0200 @@ -41,12 +41,17 @@ ``` Usage: procdump [OPTIONS...] TARGET OPTIONS - -C CPU threshold at which to create a dump of the process from 0 to 100 * nCPU - -c CPU threshold below which to create a dump of the process from 0 to 100 * nCPU - -M Memory commit threshold in MB at which to create a dump - -m Trigger when memory commit drops below specified MB value. - -n Number of dumps to write before exiting + -h Prints this help screen + -C Trigger core dump generation when CPU exceeds or equals specified value (0 to 100 * nCPU) + -c Trigger core dump generation when CPU is less than specified value (0 to 100 * nCPU) + -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. + -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) + -d Writes diagnostic logs to syslog TARGET must be exactly one of these: -p pid of the process -w Name of the process executable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/azure-pipelines.yml new/ProcDump-for-Linux-1.1.1/azure-pipelines.yml --- old/ProcDump-for-Linux-1.1/azure-pipelines.yml 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/azure-pipelines.yml 2020-04-03 21:03:02.000000000 +0200 @@ -34,14 +34,13 @@ condition: not(eq(variables['Build.Reason'], 'PullRequest')) dependsOn: - Run_Unit_Tests - variables: - Revision: '$(Build.BuildId)' steps: - script: | make displayName: 'Build procdump Ubuntu' - script: | + export REVISION=$(Build.BuildId) make release make deb displayName: 'Building debian package & artifacts' @@ -62,14 +61,13 @@ pool: 'Centos-Docker-Pool' dependsOn: - DEB_Package_Build - variables: - Revision: '$(Build.BuildId)' steps: - script: | make displayName: "Build Procdump Centos" - script: | + export REVISION=$(Build.BuildId) make release make rpm displayName: 'Building centos package & artifacts' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/dist/procdump.spec.in new/ProcDump-for-Linux-1.1.1/dist/procdump.spec.in --- old/ProcDump-for-Linux-1.1/dist/procdump.spec.in 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/dist/procdump.spec.in 2020-04-03 21:03:02.000000000 +0200 @@ -54,13 +54,17 @@ %changelog +* Fri Apr 3 2020 Javid Habibi <jahab...@microsoft.com> - 1.1.1 +- implimented thread and file descriptor count trigger +- added polling interval switch + * Mon Dec 9 2019 Javid Habibi <jahab...@microsoft.com> - 1.1 - Added support for .Net Core 3.x+ core dump generation that results in more manageable core dump sizes * Fri Nov 8 2019 Javid Habibi <jahab...@microsoft.com> - 1.0.2 -- implimented -w target flag #34 -- fixed pthread cancellation bug #49 -- added additional error checking for null process names #58 +- implimented -w target flag +- fixed pthread cancellation bug +- added additional error checking for null process names - implimented a minimal kernel check validation - various bug fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/include/CoreDumpWriter.h new/ProcDump-for-Linux-1.1.1/include/CoreDumpWriter.h --- old/ProcDump-for-Linux-1.1/include/CoreDumpWriter.h 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/include/CoreDumpWriter.h 2020-04-03 21:03:02.000000000 +0200 @@ -55,10 +55,12 @@ enum ECoreDumpType { - COMMIT, - CPU, - TIME, - MANUAL + COMMIT, // trigger on memory threshold + CPU, // trigger on CPU threshold + THREAD, // trigger on thread count + FILEDESC, // trigger on file descriptor count + TIME, // trigger on time interval + MANUAL // manual trigger }; struct CoreDumpWriter { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/include/ProcDumpConfiguration.h new/ProcDump-for-Linux-1.1.1/include/ProcDumpConfiguration.h --- old/ProcDump-for-Linux-1.1/include/ProcDumpConfiguration.h 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/include/ProcDumpConfiguration.h 2020-04-03 21:03:02.000000000 +0200 @@ -38,6 +38,8 @@ #define MIN_KERNEL_VERSION 3 #define MIN_KERNEL_PATCH 5 +#define MIN_POLLING_INTERVAL 1000 // default trigger polling interval (ms) + struct ProcDumpConfiguration g_config; // backbone of the program long HZ; // clock ticks per second @@ -78,6 +80,9 @@ int NumberOfDumpsToCollect; // -n bool WaitingForProcessName; // -w bool DiagnosticsLoggingEnabled; // -d + int ThreadThreshold; // -T + int FileDescriptorThreshold; // -F + int PollingInterval; // -I // 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/include/Process.h new/ProcDump-for-Linux-1.1.1/include/Process.h --- old/ProcDump-for-Linux-1.1/include/Process.h 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/include/Process.h 2020-04-03 21:03:02.000000000 +0200 @@ -195,6 +195,9 @@ // The thread'd exit status in the form reported by waitpid. int exit_code; + + // NOTE: This does not come from /proc/[pid]/stat rather is populated by enumerating the /proc/<pid>>/fdinfo + int num_filedescriptors; }; // @@ -270,6 +273,5 @@ // ----------------------------------------------------------- bool GetProcessStat(pid_t pid, struct ProcessStat *proc); -bool GetProcessStatus(pid_t pid, struct ProcessStatus *proc); #endif // PROCFSLIB_PROCESS_H \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/include/TriggerThreadProcs.h new/ProcDump-for-Linux-1.1.1/include/TriggerThreadProcs.h --- old/ProcDump-for-Linux-1.1/include/TriggerThreadProcs.h 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/include/TriggerThreadProcs.h 2020-04-03 21:03:02.000000000 +0200 @@ -28,8 +28,10 @@ #include "Logging.h" // worker thread process for monitoring memory commit -void *CommitThread(void *thread_args /* struct ProcDumpConfiguration* */); -void *CpuThread(void *thread_args /* struct ProcDumpConfiguration* */); +void *CommitMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); +void *CpuMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); +void *ThreadCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); +void *FileDescriptorCountMonitoringThread(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/procdump.1 new/ProcDump-for-Linux-1.1.1/procdump.1 --- old/ProcDump-for-Linux-1.1/procdump.1 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/procdump.1 2020-04-03 21:03:02.000000000 +0200 @@ -1,15 +1,20 @@ .\" Manpage for procdump. -.TH man 8 "12/09/2019" "1.1" "procdump manpage" +.TH man 8 "12/09/2019" "1.1.1" "procdump manpage" .SH NAME procdump \- generate coredumps based off performance triggers. .SH SYNOPSIS procdump [OPTIONS...] TARGET - -C CPU threshold at which to create a coredump of the process from 0 to 100 * nCPU - -c CPU threshold below which to create a coredump of the process from 0 to 100 * nCPU - -M Memory commit threshold in MB at which to create a coredump - -m Trigger when memory commit drops below specified MB value - -n Number of dumps to write before exiting - -s Consecutive seconds before dump is written (default is 10) + -h Prints this help screen + -C Trigger core dump generation when CPU exceeds or equals specified value (0 to 100 * nCPU) + -c Trigger core dump generation when CPU is less than specified value (0 to 100 * nCPU) + -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. + -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) + -d Writes diagnostic logs to syslog TARGET must be exactly one of these: -p pid of the process -w Name of the process executable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/src/CoreDumpWriter.c new/ProcDump-for-Linux-1.1.1/src/CoreDumpWriter.c --- old/ProcDump-for-Linux-1.1/src/CoreDumpWriter.c 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/src/CoreDumpWriter.c 2020-04-03 21:03:02.000000000 +0200 @@ -12,7 +12,7 @@ char *sanitize(char *processName); -static const char *CoreDumpTypeStrings[] = { "commit", "cpu", "time", "manual" }; +static const char *CoreDumpTypeStrings[] = { "commit", "cpu", "thread", "filedesc", "time", "manual" }; bool GenerateCoreClrDump(char* socketName, char* dumpFileName); bool IsCoreClrProcess(struct CoreDumpWriter *self, char** socketName); @@ -524,6 +524,9 @@ } free(outputBuffer); + // On WSL2 there is a delay between the core dump being written to disk and able to succesfully access it in the below check + sleep(1); + // validate that core dump file was generated if(access(coreDumpFileName, F_OK) != -1) { if(self->Config->nQuit){ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/src/ProcDumpConfiguration.c new/ProcDump-for-Linux-1.1.1/src/ProcDumpConfiguration.c --- old/ProcDump-for-Linux-1.1/src/ProcDumpConfiguration.c 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/src/ProcDumpConfiguration.c 2020-04-03 21:03:02.000000000 +0200 @@ -122,13 +122,16 @@ self->NumberOfDumpsToCollect = DEFAULT_NUMBER_OF_DUMPS; self->CpuThreshold = -1; self->MemoryThreshold = -1; + self->ThreadThreshold = -1; + self->FileDescriptorThreshold = -1; self->ThresholdSeconds = DEFAULT_DELTA_TIME; self->bCpuTriggerBelowValue = false; self->bMemoryTriggerBelowValue = false; self->bTimerThreshold = false; self->WaitingForProcessName = false; self->DiagnosticsLoggingEnabled = false; - self->gcorePid = NO_PID; + self->gcorePid = NO_PID; + self->PollingInterval = MIN_POLLING_INTERVAL; SetEvent(&g_evtConfigurationInitialized.event); // We've initialized and are now re-entrant safe } @@ -177,7 +180,7 @@ // parse arguments int next_option; int option_index = 0; - const char* short_options = "+p:C:c:M:m:n:s:w:dh"; + const char* short_options = "+p:C:c:M:m:n:s:w:T:F:I:dh"; const struct option long_options[] = { { "pid", required_argument, NULL, 'p' }, { "cpu", required_argument, NULL, 'C' }, @@ -187,6 +190,9 @@ { "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' }, + { "pollinginterval", required_argument, NULL, 'I' }, { "diag", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' } }; @@ -210,6 +216,29 @@ } break; + case 'I': + if (!IsValidNumberArg(optarg) || (self->PollingInterval = atoi(optarg)) < 0 || self->PollingInterval < MIN_POLLING_INTERVAL) { + Log(error, "Invalid polling interval specified (minimum %d).", MIN_POLLING_INTERVAL); + return PrintUsage(self); + } + break; + + case 'T': + if (self->ThreadThreshold != -1 || !IsValidNumberArg(optarg) || + (self->ThreadThreshold = atoi(optarg)) < 0 ) { + Log(error, "Invalid threads threshold specified."); + return PrintUsage(self); + } + break; + + case 'F': + if (self->FileDescriptorThreshold != -1 || !IsValidNumberArg(optarg) || + (self->FileDescriptorThreshold = atoi(optarg)) < 0 ) { + Log(error, "Invalid file descriptor threshold specified."); + return PrintUsage(self); + } + break; + case 'c': if (self->CpuThreshold != -1 || !IsValidNumberArg(optarg) || (self->CpuThreshold = atoi(optarg)) < 0 || self->CpuThreshold > MAXIMUM_CPU) { @@ -277,7 +306,9 @@ // if number of dumps is set, but no thresholds, just go on timer if (self->NumberOfDumpsToCollect != -1 && self->MemoryThreshold == -1 && - self->CpuThreshold == -1) { + self->CpuThreshold == -1 && + self->ThreadThreshold == -1 && + self->FileDescriptorThreshold == -1) { self->bTimerThreshold = true; } @@ -486,19 +517,33 @@ // create threads if (self->CpuThreshold != -1) { - if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, CpuThread, (void *)self)) != 0) { + if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, CpuMonitoringThread, (void *)self)) != 0) { Trace("CreateTriggerThreads: failed to create CpuThread."); return rc; } } if (self->MemoryThreshold != -1) { - if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, CommitThread, (void *)self)) != 0) { + if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, CommitMonitoringThread, (void *)self)) != 0) { Trace("CreateTriggerThreads: failed to create CommitThread."); return rc; } } + if (self->ThreadThreshold != -1) { + if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, ThreadCountMonitoringThread, (void *)self)) != 0) { + Trace("CreateTriggerThreads: failed to create ThreadThread."); + return rc; + } + } + + if (self->FileDescriptorThreshold != -1) { + if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, FileDescriptorCountMonitoringThread, (void *)self)) != 0) { + Trace("CreateTriggerThreads: failed to create FileDescriptorThread."); + return rc; + } + } + if (self->bTimerThreshold) { if ((rc = pthread_create(&self->Threads[self->nThreads++], NULL, TimerThread, (void *)self)) != 0) { Trace("CreateTriggerThreads: failed to create TimerThread."); @@ -666,8 +711,21 @@ printf("Commit Threshold:\tn/a\n"); } + // Thread + if (self->ThreadThreshold != -1) { + printf("Thread Threshold:\t>=%d\n", self->ThreadThreshold); + } + + // File descriptor + if (self->FileDescriptorThreshold != -1) { + printf("File descriptor Threshold:\t>=%d\n", self->FileDescriptorThreshold); + } + + // Polling inverval + printf("Polling interval (ms):\t%d\n", self->PollingInterval); + // time - printf("Threshold Seconds:\t%d\n", self->ThresholdSeconds); + printf("Threshold (s):\t%d\n", self->ThresholdSeconds); // number of dumps and others printf("Number of Dumps:\t%d\n", self->NumberOfDumpsToCollect); @@ -775,7 +833,7 @@ //-------------------------------------------------------------------- void PrintBanner() { - printf("\nProcDump v1.1 - Sysinternals process dump utility\n"); + 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("Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi\n"); @@ -794,11 +852,14 @@ printf("\nUsage: procdump [OPTIONS...] TARGET\n"); printf(" OPTIONS\n"); printf(" -h Prints this help screen\n"); - printf(" -C CPU threshold at which to create a dump of the process from 0 to 100 * nCPU\n"); - printf(" -c CPU threshold below which to create a dump of the process from 0 to 100 * nCPU\n"); - printf(" -M Memory commit threshold in MB at which to create a dump\n"); - printf(" -m Trigger when memory commit drops below specified MB value.\n"); - printf(" -n Number of dumps to write before exiting (default is %d)\n", DEFAULT_NUMBER_OF_DUMPS); + printf(" -C Trigger core dump generation when CPU exceeds or equals specified value (0 to 100 * nCPU)\n"); + printf(" -c Trigger core dump generation when CPU is less than specified value (0 to 100 * nCPU)\n"); + 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(" -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(" -d Writes diagnostic logs to syslog\n"); printf(" TARGET must be exactly one of these:\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/src/Process.c new/ProcDump-for-Linux-1.1.1/src/Process.c --- old/ProcDump-for-Linux-1.1/src/Process.c 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/src/Process.c 2020-04-03 21:03:02.000000000 +0200 @@ -7,6 +7,9 @@ // //-------------------------------------------------------------------- +#include <dirent.h> +#include <sys/stat.h> + #include "Process.h" bool GetProcessStat(pid_t pid, struct ProcessStat *proc) { @@ -16,6 +19,34 @@ char *savePtr = NULL; FILE *procFile = NULL; + DIR* fddir = NULL; + struct dirent* entry = NULL; + + // Get number of file descriptors in /proc/%d/fdinfo. This directory only contains sub directories for each file descriptor. + if(sprintf(procFilePath, "/proc/%d/fdinfo", pid) < 0){ + return false; + } + + fddir = opendir(procFilePath); + if(fddir) + { + proc->num_filedescriptors = 0; + while ((entry = readdir(fddir)) != NULL) + { + proc->num_filedescriptors++; + } + + closedir(fddir); + } + else + { + Log(error, "Failed to open %s. Exiting...\n", procFilePath); + return false; + + } + + proc->num_filedescriptors-=2; // Account for "." and ".." + // Read /proc/[pid]/stat if(sprintf(procFilePath, "/proc/%d/stat", pid) < 0){ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ProcDump-for-Linux-1.1/src/TriggerThreadProcs.c new/ProcDump-for-Linux-1.1.1/src/TriggerThreadProcs.c --- old/ProcDump-for-Linux-1.1/src/TriggerThreadProcs.c 2019-12-13 19:22:42.000000000 +0100 +++ new/ProcDump-for-Linux-1.1.1/src/TriggerThreadProcs.c 2020-04-03 21:03:02.000000000 +0200 @@ -9,9 +9,9 @@ #include "TriggerThreadProcs.h" -void *CommitThread(void *thread_args /* struct ProcDumpConfiguration* */) +void *CommitMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) { - Trace("CommitThread: Starting Trigger Thread"); + Trace("CommitMonitoringThread: Starting Trigger Thread"); struct ProcDumpConfiguration *config = (struct ProcDumpConfiguration *)thread_args; long pageSize_kb; @@ -24,7 +24,7 @@ if ((rc = WaitForQuitOrEvent(config, &config->evtStartMonitoring, INFINITE_WAIT)) == WAIT_OBJECT_0 + 1) { - while ((rc = WaitForQuit(config, 1000)) == WAIT_TIMEOUT) + while ((rc = WaitForQuit(config, config->PollingInterval)) == WAIT_TIMEOUT) { if (GetProcessStat(config->ProcessId, &proc)) { @@ -51,22 +51,95 @@ exit(-1); } } + } + + free(writer); + Trace("CommitMonitoringThread: Exiting Trigger Thread"); + pthread_exit(NULL); +} + +void* ThreadCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) +{ + Trace("ThreadCountMonitoringThread: Starting Thread Thread"); + struct ProcDumpConfiguration *config = (struct ProcDumpConfiguration *)thread_args; + + struct ProcessStat proc = {0}; + int rc = 0; + struct CoreDumpWriter *writer = NewCoreDumpWriter(THREAD, config); - // handle exit cases - if (rc == WAIT_ABANDONED || rc == WAIT_OBJECT_0) + if ((rc = WaitForQuitOrEvent(config, &config->evtStartMonitoring, INFINITE_WAIT)) == WAIT_OBJECT_0 + 1) + { + while ((rc = WaitForQuit(config, config->PollingInterval)) == WAIT_TIMEOUT) { - // clean up! + if (GetProcessStat(config->ProcessId, &proc)) + { + if (proc.num_threads >= config->ThreadThreshold) + { + Log(info, "Threads: %ld", proc.num_threads); + rc = WriteCoreDump(writer); + + if ((rc = WaitForQuit(config, config->ThresholdSeconds * 1000)) != WAIT_TIMEOUT) + { + break; + } + } + } + else + { + Log(error, "An error occured while parsing procfs\n"); + exit(-1); + } } } free(writer); - Trace("CommitThread: Exiting Trigger Thread"); + Trace("ThreadCountMonitoringThread: Exiting Thread trigger Thread"); pthread_exit(NULL); } -void *CpuThread(void *thread_args /* struct ProcDumpConfiguration* */) + +void* FileDescriptorCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) { - Trace("CpuThread: Starting Trigger Thread"); + Trace("FileDescriptorCountMonitoringThread: Starting Filedescriptor Thread"); + struct ProcDumpConfiguration *config = (struct ProcDumpConfiguration *)thread_args; + + struct ProcessStat proc = {0}; + int rc = 0; + struct CoreDumpWriter *writer = NewCoreDumpWriter(FILEDESC, config); + + if ((rc = WaitForQuitOrEvent(config, &config->evtStartMonitoring, INFINITE_WAIT)) == WAIT_OBJECT_0 + 1) + { + while ((rc = WaitForQuit(config, config->PollingInterval)) == WAIT_TIMEOUT) + { + if (GetProcessStat(config->ProcessId, &proc)) + { + if (proc.num_filedescriptors >= config->FileDescriptorThreshold) + { + Log(info, "File descriptors: %ld", proc.num_filedescriptors); + rc = WriteCoreDump(writer); + + if ((rc = WaitForQuit(config, config->ThresholdSeconds * 1000)) != WAIT_TIMEOUT) + { + break; + } + } + } + else + { + Log(error, "An error occured while parsing procfs\n"); + exit(-1); + } + } + } + + free(writer); + Trace("FileDescriptorCountMonitoringThread: Exiting Filedescriptor trigger Thread"); + pthread_exit(NULL); +} + +void *CpuMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */) +{ + Trace("CpuMonitoringThread: Starting Trigger Thread"); struct ProcDumpConfiguration *config = (struct ProcDumpConfiguration *)thread_args; unsigned long totalTime = 0; @@ -80,7 +153,7 @@ if ((rc = WaitForQuitOrEvent(config, &config->evtStartMonitoring, INFINITE_WAIT)) == WAIT_OBJECT_0 + 1) { - while ((rc = WaitForQuit(config, 1000)) == WAIT_TIMEOUT) + while ((rc = WaitForQuit(config, config->PollingInterval)) == WAIT_TIMEOUT) { sysinfo(&sysInfo); @@ -110,16 +183,10 @@ exit(-1); } } - - // handle exit cases - if (rc == WAIT_ABANDONED || rc == WAIT_OBJECT_0) - { - // clean up! - } } free(writer); - Trace("CpuThread: Exiting Trigger Thread"); + Trace("CpuTCpuMonitoringThread: Exiting Trigger Thread"); pthread_exit(NULL); } @@ -143,15 +210,9 @@ break; } } - - // handle exit cases - if (rc == WAIT_ABANDONED || rc == WAIT_OBJECT_0) - { - // clean up! - } } free(writer); Trace("TimerThread: Exiting Trigger Thread"); pthread_exit(NULL); -} \ No newline at end of file +} ++++++ procdump-gcc10.patch ++++++ >From 0d98403557465dd12e4f8d33a673d98b3468dd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Grabovsk=C3=BD?= <mgrab...@redhat.com> Date: Thu, 20 Feb 2020 10:11:47 +0100 Subject: [PATCH] Fix for build on GCC 10 GCC 10 defaults to -fno-common which requires us to explicitly mark global variables with extern in header files. --- include/Logging.h | 6 ++---- include/ProcDumpConfiguration.h | 6 +++--- src/ProcDumpConfiguration.c | 6 ++++++ 3 files changed, 11 insertions(+), 7 deletions(-) Index: ProcDump-for-Linux-1.1.1/include/Logging.h =================================================================== --- ProcDump-for-Linux-1.1.1.orig/include/Logging.h +++ ProcDump-for-Linux-1.1.1/include/Logging.h @@ -26,8 +26,6 @@ #define S2(x) S1(x) #define LOCATION "in "__FILE__ ", at line " S2(__LINE__) -extern struct ProcDumpConfiguration g_config; - enum LogLevel{ debug, @@ -39,7 +37,7 @@ enum LogLevel{ void Log(enum LogLevel logLevel, const char *message, ...); -pthread_mutex_t LoggerLock; +extern pthread_mutex_t LoggerLock; void DiagTrace(const char* message, ...); @@ -54,4 +52,4 @@ void DiagTrace(const char* message, ...) #define Trace(format, ...) \ DiagTrace(format " %s", ##__VA_ARGS__, LOCATION); -#endif // LOGGING_H \ No newline at end of file +#endif // LOGGING_H Index: ProcDump-for-Linux-1.1.1/include/ProcDumpConfiguration.h =================================================================== --- ProcDump-for-Linux-1.1.1.orig/include/ProcDumpConfiguration.h +++ ProcDump-for-Linux-1.1.1/include/ProcDumpConfiguration.h @@ -40,10 +40,10 @@ #define MIN_POLLING_INTERVAL 1000 // default trigger polling interval (ms) -struct ProcDumpConfiguration g_config; // backbone of the program +extern struct ProcDumpConfiguration g_config; // backbone of the program -long HZ; // clock ticks per second -int MAXIMUM_CPU; // maximum cpu usage percentage (# cores * 100) +extern long HZ; // clock ticks per second +extern int MAXIMUM_CPU; // maximum cpu usage percentage (# cores * 100) // ------------------- // Structs Index: ProcDump-for-Linux-1.1.1/src/ProcDumpConfiguration.c =================================================================== --- ProcDump-for-Linux-1.1.1.orig/src/ProcDumpConfiguration.c +++ ProcDump-for-Linux-1.1.1/src/ProcDumpConfiguration.c @@ -12,6 +12,12 @@ struct Handle g_evtConfigurationInitialized = HANDLE_MANUAL_RESET_EVENT_INITIALIZER("ConfigurationInitialized"); +pthread_mutex_t LoggerLock; +struct ProcDumpConfiguration g_config; + +long HZ; +int MAXIMUM_CPU; + static sigset_t sig_set; static pthread_t sig_thread_id;