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;
 

Reply via email to