From 8c1622d4a012ddb45e4dfed0fbc2199787e30f50 Mon Sep 17 00:00:00 2001 From: Mario Hewardt Date: Thu, 18 Jan 2024 10:28:16 -0800 Subject: [PATCH 1/4] Check-point --- include/GenHelpers.h | 3 ++ include/ProcDumpConfiguration.h | 4 +- src/CoreDumpWriter.cpp | 36 ++++++++++--- src/GenHelpers.cpp | 87 ++++++++++++++++++++++++++++++ src/Monitor.cpp | 26 ++++----- src/ProcDumpConfiguration.cpp | 95 ++++++++++++++++++++++++++++----- src/Procdump.cpp | 7 +++ src/Process.cpp | 68 +++++++++++++++++------ 8 files changed, 276 insertions(+), 50 deletions(-) diff --git a/include/GenHelpers.h b/include/GenHelpers.h index 41827a5..d9c6229 100644 --- a/include/GenHelpers.h +++ b/include/GenHelpers.h @@ -108,6 +108,7 @@ static inline void cancel_pthread(unsigned long* val) int* GetSeparatedValues(char* src, char* separator, int* numValues); bool ConvertToInt(const char* src, int* conv); +bool ConvertToIntHex(const char* src, int* conv); bool IsValidNumberArg(const char *arg); bool CheckKernelVersion(int major, int minor); uint16_t* GetUint16(char* buffer); @@ -121,6 +122,8 @@ char* GetSocketPath(char* prefix, pid_t pid, pid_t targetPid); int send_all(int socket, void *buffer, size_t length); int recv_all(int socket, void* buffer, size_t length); pid_t gettid() noexcept; +unsigned long GetCoreDumpFilter(int pid); +bool SetCoreDumpFilter(int pid, unsigned long filter); #endif // GENHELPERS_H diff --git a/include/ProcDumpConfiguration.h b/include/ProcDumpConfiguration.h index 32e2352..65156ac 100644 --- a/include/ProcDumpConfiguration.h +++ b/include/ProcDumpConfiguration.h @@ -104,7 +104,8 @@ struct ProcDumpConfiguration bool DiagnosticsLoggingEnabled; // -log int ThreadThreshold; // -tc int FileDescriptorThreshold; // -fc - int SignalNumber; // -sig + int* SignalNumber; // -sig + int SignalCount; int PollingInterval; // -pf char *CoreDumpPath; // char *CoreDumpName; // @@ -115,6 +116,7 @@ struct ProcDumpConfiguration bool bRestrackEnabled; // -restrack bool bLeakReportInProgress; int SampleRate; // Record every X resource allocation in restrack + int CoreDumpMask; // -mc (core dump mask) // // Keeps track of the memory allocations when -restrack is specified. diff --git a/src/CoreDumpWriter.cpp b/src/CoreDumpWriter.cpp index c0d6617..129f785 100644 --- a/src/CoreDumpWriter.cpp +++ b/src/CoreDumpWriter.cpp @@ -106,32 +106,54 @@ char* WriteCoreDump(struct CoreDumpWriter *self) // Enter critical section (block till we decrement semaphore) rc = WaitForQuitOrEvent(self->Config, &self->Config->semAvailableDumpSlots, INFINITE_WAIT); - if(rc == 0){ + if(rc == 0) + { Log(error, INTERNAL_ERROR); Trace("WriteCoreDump: failed WaitForQuitOrEvent."); exit(-1); } - if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0){ + if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) + { Log(error, INTERNAL_ERROR); Trace("WriteCoreDump: failed pthread_setcanceltype."); exit(-1); } - switch (rc) { + switch (rc) + { case WAIT_OBJECT_0: // QUIT! Time for cleanup, no dump break; case WAIT_OBJECT_0+1: // We got a dump slot! { char* socketName = NULL; IsCoreClrProcess(self->Config->ProcessId, &socketName); - if ((dumpFileName = WriteCoreDumpInternal(self, socketName)) != NULL) { + unsigned int currentCoreDumpFilter = -1; + if(self->Config->CoreDumpMask != -1) + { + currentCoreDumpFilter = GetCoreDumpFilter(self->Config->ProcessId); + SetCoreDumpFilter(self->Config->ProcessId, self->Config->CoreDumpMask); + } + if ((dumpFileName = WriteCoreDumpInternal(self, socketName)) != NULL) + { // We're done here, unlock (increment) the sem - if(sem_post(&self->Config->semAvailableDumpSlots.semaphore) == -1){ + if(sem_post(&self->Config->semAvailableDumpSlots.semaphore) == -1) + { Log(error, INTERNAL_ERROR); Trace("WriteCoreDump: failed sem_post."); if(socketName) free(socketName); + if(self->Config->CoreDumpMask != -1 && currentCoreDumpFilter != -1) + { + SetCoreDumpFilter(self->Config->ProcessId, currentCoreDumpFilter); + } + exit(-1); } } + + if(self->Config->CoreDumpMask != -1 && currentCoreDumpFilter != -1) + { + SetCoreDumpFilter(self->Config->ProcessId, currentCoreDumpFilter); + } + if(socketName) free(socketName); } break; @@ -141,7 +163,9 @@ char* WriteCoreDump(struct CoreDumpWriter *self) Trace("WriteCoreDump: Error in default case"); break; } - if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0){ + + if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0) + { Log(error, INTERNAL_ERROR); Trace("WriteCoreDump: failed pthread_setcanceltype."); exit(-1); diff --git a/src/GenHelpers.cpp b/src/GenHelpers.cpp index f0cad62..f97b756 100644 --- a/src/GenHelpers.cpp +++ b/src/GenHelpers.cpp @@ -94,6 +94,45 @@ bool ConvertToInt(const char* src, int* conv) return true; } +//-------------------------------------------------------------------- +// +// ConvertToIntHex - Helper to convert from a char* (hex) to int +// +//-------------------------------------------------------------------- +bool ConvertToIntHex(const char* src, int* conv) +{ + int temp = 0; + + for (size_t i=0; src[i] != '\0'; i++) + { + if ((src[i] >= '0') && (src[i] <= '9')) + { + // Shift left by 0x10 (16) and add the digit using an ASCII delta + temp *= 0x10; + temp += src[i] - '0'; + } + else if ((src[i] >= 'A') && (src[i] <= 'F')) + { + // Shift left by 0x10 (16) and add the digit using an ASCII delta + temp *= 0x10; + temp += 10 + (src[i] - 'A'); + } + else if ((src[i] >= 'a') && (src[i] <= 'f')) + { + // Shift left by 0x10 (16) and add the digit using an ASCII delta + temp *= 0x10; + temp += 10 + (src[i] - 'a'); + } + else + { + return false; + } + } + + *conv = temp; + return true; +} + //-------------------------------------------------------------------- // // CheckKernelVersion - Check to see if current kernel is greater than @@ -571,3 +610,51 @@ pid_t gettid() noexcept return 0; } + +//-------------------------------------------------------------------- +// +// GetCoreDumpFilter +// +// Returns the core dump filter for the specified process id. +//-------------------------------------------------------------------- +unsigned long GetCoreDumpFilter(int pid) +{ + unsigned long filter = -1; + + char filepath[PATH_MAX]; + snprintf(filepath, sizeof(filepath), "/proc/%d/coredump_filter", pid); + + FILE* file = fopen(filepath, "r"); + if (file != NULL) + { + fscanf(file, "%lx", &filter); + } + + fclose(file); + return filter; +} + +//-------------------------------------------------------------------- +// +// SetCoreDumpFilter +// +// Sets the core dump filter for the specified process id. +//-------------------------------------------------------------------- +bool SetCoreDumpFilter(int pid, unsigned long filter) +{ + bool ret = false; + char filepath[PATH_MAX]; + snprintf(filepath, sizeof(filepath), "/proc/%d/coredump_filter", pid); + + FILE *file = fopen(filepath, "w"); + if (file != NULL) + { + if(fprintf(file, "%ld", filter) > 0) + { + ret = true; + } + } + + fclose(file); + return ret; +} diff --git a/src/Monitor.cpp b/src/Monitor.cpp index e6711ae..02cc14a 100644 --- a/src/Monitor.cpp +++ b/src/Monitor.cpp @@ -95,7 +95,7 @@ void* SignalThread(void *input) // 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(it->second->SignalNumber != -1) + if(it->second->SignalCount > 0) { for(int i=0; isecond->nThreads; i++) { @@ -537,7 +537,7 @@ int CreateMonitorThreads(struct ProcDumpConfiguration *self) } } - if (self->SignalNumber != -1 && !tooManyTriggers) + if (self->SignalCount > 0 && !tooManyTriggers) { if ((rc = CreateMonitorThread(self, Signal, SignalMonitoringThread, (void *)self)) != 0 ) { @@ -1152,7 +1152,17 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* // We are now in a signal-stop state signum = WSTOPSIG(wstatus); - if(signum == config->SignalNumber) + bool found = false; + for(int i = 0; i < config->SignalCount; i++) + { + if(signum == config->SignalNumber[i]) + { + found = true; + break; + } + } + + if(found == true) { // We have to detach in a STOP state so we can invoke gcore if(ptrace(PTRACE_DETACH, config->ProcessId, 0, SIGSTOP) == -1) @@ -1186,7 +1196,7 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* } } - kill(config->ProcessId, SIGCONT); + ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); if(config->NumberOfDumpsCollected >= config->NumberOfDumpsToCollect) { @@ -1196,8 +1206,6 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* break; } - ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); - // Re-attach to the target process if (ptrace(PTRACE_SEIZE, config->ProcessId, NULL, NULL) == -1) { @@ -1209,15 +1217,9 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* pthread_mutex_unlock(&config->ptrace_mutex); continue; } - // Resume execution of the target process ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); pthread_mutex_unlock(&config->ptrace_mutex); - - if(dumpFileName == NULL) - { - break; - } } } } diff --git a/src/ProcDumpConfiguration.cpp b/src/ProcDumpConfiguration.cpp index 1a08d20..f0c08f7 100644 --- a/src/ProcDumpConfiguration.cpp +++ b/src/ProcDumpConfiguration.cpp @@ -162,7 +162,8 @@ void InitProcDumpConfiguration(struct ProcDumpConfiguration *self) self->DumpGCGeneration = -1; self->ThreadThreshold = -1; self->FileDescriptorThreshold = -1; - self->SignalNumber = -1; + self->SignalNumber = NULL; + self->SignalCount = 0; self->ThresholdSeconds = -1; self->bMemoryTriggerBelowValue = false; self->bTimerThreshold = false; @@ -180,6 +181,7 @@ void InitProcDumpConfiguration(struct ProcDumpConfiguration *self) self->bRestrackEnabled = false; self->bLeakReportInProgress = false; self->SampleRate = 0; + self->CoreDumpMask = -1; self->socketPath = NULL; self->statusSocket = -1; @@ -266,6 +268,12 @@ void FreeProcDumpConfiguration(struct ProcDumpConfiguration *self) self->MemoryThreshold = NULL; } + if(self->SignalNumber) + { + free(self->SignalNumber); + self->SignalNumber = NULL; + } + for (const auto& pair : self->memAllocMap) { if(pair.second) @@ -336,6 +344,7 @@ struct ProcDumpConfiguration * CopyProcDumpConfiguration(struct ProcDumpConfigur copy->bRestrackEnabled = self->bRestrackEnabled; copy->bLeakReportInProgress = self->bLeakReportInProgress; copy->SampleRate = self->SampleRate; + copy->CoreDumpMask = self->CoreDumpMask; copy->bMemoryTriggerBelowValue = self->bMemoryTriggerBelowValue; copy->MemoryThresholdCount = self->MemoryThresholdCount; copy->bMonitoringGCMemory = self->bMonitoringGCMemory; @@ -347,7 +356,30 @@ struct ProcDumpConfiguration * CopyProcDumpConfiguration(struct ProcDumpConfigur copy->DiagnosticsLoggingEnabled = self->DiagnosticsLoggingEnabled; copy->ThreadThreshold = self->ThreadThreshold; copy->FileDescriptorThreshold = self->FileDescriptorThreshold; - copy->SignalNumber = self->SignalNumber; + + if(self->SignalNumber != NULL) + { + copy->SignalCount = self->SignalCount; + copy->SignalNumber = (int*) malloc(self->SignalCount*sizeof(int)); + if(copy->SignalNumber == NULL) + { + Trace("Failed to alloc memory for SignalNumber"); + if(copy->ProcessName) + { + free(copy->ProcessName); + } + + if(copy->MemoryThreshold) + { + free(copy->MemoryThreshold); + } + + return NULL; + } + + memcpy(copy->SignalNumber, self->SignalNumber, self->SignalCount*sizeof(int)); + } + copy->PollingInterval = self->PollingInterval; copy->CoreDumpPath = self->CoreDumpPath == NULL ? NULL : strdup(self->CoreDumpPath); copy->CoreDumpName = self->CoreDumpName == NULL ? NULL : strdup(self->CoreDumpName); @@ -584,11 +616,32 @@ int GetOptions(struct ProcDumpConfiguration *self, int argc, char *argv[]) else if( 0 == strcasecmp( argv[i], "/sig" ) || 0 == strcasecmp( argv[i], "-sig" )) { - if( i+1 >= argc || self->SignalNumber != -1 ) return PrintUsage(); - if(!ConvertToInt(argv[i+1], &self->SignalNumber)) return PrintUsage(); - if(self->SignalNumber < 0) + if( i+1 >= argc || self->SignalCount != 0 ) return PrintUsage(); + self->SignalNumber = GetSeparatedValues(argv[i+1], const_cast(","), &self->SignalCount); + + if(self->SignalNumber == NULL || self->SignalCount == 0) return PrintUsage(); + + for(int i = 0; i < self->SignalCount; i++) + { + if(self->SignalNumber[i] < 0) + { + Log(error, "Invalid signal specified."); + free(self->SignalNumber); + return PrintUsage(); + } + } + + i++; + } + else if( 0 == strcasecmp( argv[i], "/mc" ) || + 0 == strcasecmp( argv[i], "-mc" )) + { + if( i+1 >= argc || self->CoreDumpMask != -1 ) return PrintUsage(); + + if(ConvertToIntHex(argv[i+1], &self->CoreDumpMask) == false) return PrintUsage(); + if(self->CoreDumpMask < 0) { - Log(error, "Invalid signal specified."); + Log(error, "Invalid core dump mask specified."); return PrintUsage(); } @@ -896,13 +949,14 @@ int GetOptions(struct ProcDumpConfiguration *self, int argc, char *argv[]) (self->MemoryThreshold == NULL) && (self->ThreadThreshold == -1) && (self->FileDescriptorThreshold == -1) && - (self->DumpGCGeneration == -1)) + (self->DumpGCGeneration == -1) && + (self->SignalCount == 0)) { self->bTimerThreshold = true; } // Signal trigger can only be specified alone - if(self->SignalNumber != -1 || self->bDumpOnException) + if(self->SignalCount > 0 || self->bDumpOnException) { if(self->CpuThreshold != -1 || self->ThreadThreshold != -1 || self->FileDescriptorThreshold != -1 || self->MemoryThreshold != NULL) { @@ -931,7 +985,6 @@ int GetOptions(struct ProcDumpConfiguration *self, int argc, char *argv[]) ApplyDefaults(self); Trace("GetOpts and initial Configuration finished"); - return 0; } @@ -944,7 +997,7 @@ bool PrintConfiguration(struct ProcDumpConfiguration *self) { if (WaitForSingleObject(&self->evtConfigurationPrinted,0) == WAIT_TIMEOUT) { - if(self->SignalNumber != -1) + if(self->SignalCount > 0) { printf("** NOTE ** Signal triggers use PTRACE which will impact the performance of the target process\n\n"); } @@ -1047,9 +1100,21 @@ bool PrintConfiguration(struct ProcDumpConfiguration *self) } // Signal - if (self->SignalNumber != -1) + if (self->SignalCount > 0) { - printf("%-40s%d\n", "Signal:", self->SignalNumber); + printf("%-40s", "Signal(s):"); + for(int i=0; iSignalCount; i++) + { + printf("%d", self->SignalNumber[i]); + if(i < self->SignalCount -1) + { + printf(","); + } + else + { + printf("\n"); + } + } } else { @@ -1138,10 +1203,11 @@ int PrintUsage() printf(" [-sr Sample_Rate]\n"); printf(" [-tc Thread_Threshold]\n"); printf(" [-fc FileDescriptor_Threshold]\n"); - printf(" [-sig Signal_Number]\n"); + printf(" [-sig Signal_Number1[,Signal_Number2...]]\n"); printf(" [-e]\n"); printf(" [-f Include_Filter,...]\n"); printf(" [-fx Exclude_Filter]\n"); + printf(" [-mc Custom_Dump_Mask]\n"); printf(" [-pf Polling_Frequency]\n"); printf(" [-o]\n"); printf(" [-log]\n"); @@ -1162,10 +1228,11 @@ int PrintUsage() printf(" -sr Sample rate when using -restrack.\n"); printf(" -tc Thread count threshold above which to create a dump of the process.\n"); printf(" -fc File descriptor count threshold above which to create a dump of the process.\n"); - printf(" -sig Signal number to intercept to create a dump of the process.\n"); + printf(" -sig Comma separated list of signal number(s) during which either signal results in a dump of the process.\n"); printf(" -e [.NET] Create dump when the process encounters an exception.\n"); printf(" -f Filter (include) on the content of .NET exceptions (comma separated). Wildcards (*) are supported.\n"); printf(" -fx Filter (exclude) on the content of -restrack call stacks. Wildcards (*) are supported.\n"); + printf(" -mc Custom core dump mask (in hex) indicating what memory should be included in the core dump. Please see 'man core' (/proc/[pid]/coredump_filter) for available options.\n"); printf(" -pf Polling frequency.\n"); printf(" -o Overwrite existing dump file.\n"); printf(" -log Writes extended ProcDump tracing to syslog.\n"); diff --git a/src/Procdump.cpp b/src/Procdump.cpp index 7241e88..2a18a2c 100644 --- a/src/Procdump.cpp +++ b/src/Procdump.cpp @@ -9,6 +9,8 @@ //-------------------------------------------------------------------- #include "Includes.h" +#include + extern struct ProcDumpConfiguration g_config; //-------------------------------------------------------------------- @@ -54,6 +56,11 @@ int main(int argc, char *argv[]) // Register exit handler atexit(OnExit); + struct rlimit rlim; + rlim.rlim_cur = 1000000000; + rlim.rlim_max = 1000000000; + setrlimit(RLIMIT_CORE, &rlim); + // monitor for all specified processes MonitorProcesses(&g_config); } diff --git a/src/Process.cpp b/src/Process.cpp index 4c52b4d..cc7af4a 100644 --- a/src/Process.cpp +++ b/src/Process.cpp @@ -7,6 +7,7 @@ // //-------------------------------------------------------------------- #include "Includes.h" +#include //-------------------------------------------------------------------- // @@ -517,6 +518,28 @@ bool GetProcessStat(pid_t pid, struct ProcessStat *proc) { return true; } +//-------------------------------------------------------------------- +// +// GetProcessName - Gets the process name only in cases where the +// specified process name is the command line and +// contains arguments. +// +//-------------------------------------------------------------------- +char * GetProcessName(char* processName) +{ + char* retString = processName; + + std::string procName = ""; + std::string inputString = processName; + size_t firstSpacePos = inputString.find(' '); + if (firstSpacePos != std::string::npos) + { + procName = inputString.substr(0, firstSpacePos); + retString = const_cast(procName.c_str()); + } + + return strdup(retString); +} //-------------------------------------------------------------------- // @@ -524,7 +547,8 @@ bool GetProcessStat(pid_t pid, struct ProcessStat *proc) { // Returns EMPTY_PROC_NAME for null process name. // //-------------------------------------------------------------------- -char * GetProcessName(pid_t pid){ +char * GetProcessName(pid_t pid) +{ char procFilePath[32]; char fileBuffer[MAX_CMDLINE_LEN]; int charactersRead = 0; @@ -533,24 +557,27 @@ char * GetProcessName(pid_t pid){ char * processName; auto_free_file FILE * procFile = NULL; - if(sprintf(procFilePath, "/proc/%d/cmdline", pid) < 0) { + if(sprintf(procFilePath, "/proc/%d/cmdline", pid) < 0) + { return NULL; } procFile = fopen(procFilePath, "r"); - if(procFile != NULL) { - if(fgets(fileBuffer, MAX_CMDLINE_LEN, procFile) == NULL) { - - if(strlen(fileBuffer) == 0) { + if(procFile != NULL) + { + if(fgets(fileBuffer, MAX_CMDLINE_LEN, procFile) == NULL) + { + if(strlen(fileBuffer) == 0) + { Log(debug, "Empty cmdline.\n"); } - else{ - } + return NULL; } } - else { + else + { Log(debug, "Failed to open %s.\n", procFilePath); return NULL; } @@ -559,21 +586,28 @@ char * GetProcessName(pid_t pid){ // Extract process name stringItr = fileBuffer; charactersRead = strlen(fileBuffer); - for(int i = 0; i <= charactersRead; i++){ - if(fileBuffer[i] == '\0'){ + for(int i = 0; i <= charactersRead; i++) + { + if(fileBuffer[i] == '\0') + { itr = i - itr; - if(strcmp(stringItr, "sudo") != 0){ // do we have the process name including filepath? + // do we have the process name including filepath? + if(strcmp(stringItr, "sudo") != 0) + { processName = strrchr(stringItr, '/'); // does this process include a filepath? - if(processName != NULL){ - return strdup(processName + 1); // +1 to not include '/' character + if(processName != NULL) + { + return GetProcessName(processName + 1); // +1 to not include '/' character } - else{ - return strdup(stringItr); + else + { + return GetProcessName(stringItr); } } - else{ + else + { stringItr += (itr+1); // +1 to move past '\0' } } From 46b4a44d9ceaef832e52f193cc07bda868269bd6 Mon Sep 17 00:00:00 2001 From: Mario Hewardt Date: Thu, 18 Jan 2024 10:32:24 -0800 Subject: [PATCH 2/4] Fix compilation error --- src/GenHelpers.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/GenHelpers.cpp b/src/GenHelpers.cpp index f97b756..7624836 100644 --- a/src/GenHelpers.cpp +++ b/src/GenHelpers.cpp @@ -627,7 +627,11 @@ unsigned long GetCoreDumpFilter(int pid) FILE* file = fopen(filepath, "r"); if (file != NULL) { - fscanf(file, "%lx", &filter); + int itemsRead = fscanf(file, "%lx", &filter); + if (itemsRead != 1) + { + filter = -1; + } } fclose(file); From 0e9db630c1374c478b2247213ce9d00ce58f758a Mon Sep 17 00:00:00 2001 From: Mario Hewardt Date: Mon, 22 Jan 2024 10:01:47 -0800 Subject: [PATCH 3/4] Cleanup --- CMakeLists.txt | 2 +- include/Process.h | 3 ++- src/Monitor.cpp | 13 ++++++------- src/Procdump.cpp | 7 ------- src/Process.cpp | 15 +++++++-------- 5 files changed, 16 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fdb921..d369757 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,7 +181,7 @@ add_executable(procdump ${PROJECT_BINARY_DIR}/ProcDumpProfiler.o ) -target_compile_options(procdump PRIVATE -g -pthread -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Werror -D_GNU_SOURCE -std=c++11 -O2) +target_compile_options(procdump PRIVATE -g -pthread -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Werror -D_GNU_SOURCE -std=c++11) target_include_directories(procdump PUBLIC ${procdump_INC} diff --git a/include/Process.h b/include/Process.h index 5efe91a..654962a 100644 --- a/include/Process.h +++ b/include/Process.h @@ -276,7 +276,8 @@ struct ProcessStatus { // ----------------------------------------------------------- bool GetProcessStat(pid_t pid, struct ProcessStat *proc); -char * GetProcessName(pid_t pid); +char* GetProcessName(pid_t pid); +char* GetProcessNameFromCmdLine(char* cmdLine); pid_t GetProcessPgid(pid_t pid); bool LookupProcessByPid(pid_t pid); bool LookupProcessByPgid(pid_t pid); diff --git a/src/Monitor.cpp b/src/Monitor.cpp index 02cc14a..1af8e5f 100644 --- a/src/Monitor.cpp +++ b/src/Monitor.cpp @@ -1177,7 +1177,9 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* dumpFileName = WriteCoreDump(writer); if(dumpFileName == NULL) { - SetQuit(config, 1); + ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); + ptrace(PTRACE_DETACH, config->ProcessId, 0, 0); + break; } // @@ -1186,11 +1188,7 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* if(config->bRestrackEnabled == true) { pthread_t id = WriteRestrackSnapshot(config, (std::string(dumpFileName) + ".restrack").c_str()); - if (id == 0) - { - SetQuit(config, 1); - } - else + if (id != 0) { leakReportThreads.push_back(id); } @@ -1201,8 +1199,8 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* 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(&config->ptrace_mutex); + ptrace(PTRACE_DETACH, config->ProcessId, 0, 0); break; } @@ -1217,6 +1215,7 @@ void* SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* pthread_mutex_unlock(&config->ptrace_mutex); continue; } + // Resume execution of the target process ptrace(PTRACE_CONT, config->ProcessId, NULL, signum); pthread_mutex_unlock(&config->ptrace_mutex); diff --git a/src/Procdump.cpp b/src/Procdump.cpp index 2a18a2c..7241e88 100644 --- a/src/Procdump.cpp +++ b/src/Procdump.cpp @@ -9,8 +9,6 @@ //-------------------------------------------------------------------- #include "Includes.h" -#include - extern struct ProcDumpConfiguration g_config; //-------------------------------------------------------------------- @@ -56,11 +54,6 @@ int main(int argc, char *argv[]) // Register exit handler atexit(OnExit); - struct rlimit rlim; - rlim.rlim_cur = 1000000000; - rlim.rlim_max = 1000000000; - setrlimit(RLIMIT_CORE, &rlim); - // monitor for all specified processes MonitorProcesses(&g_config); } diff --git a/src/Process.cpp b/src/Process.cpp index cc7af4a..f96ea81 100644 --- a/src/Process.cpp +++ b/src/Process.cpp @@ -520,17 +520,16 @@ bool GetProcessStat(pid_t pid, struct ProcessStat *proc) { //-------------------------------------------------------------------- // -// GetProcessName - Gets the process name only in cases where the -// specified process name is the command line and -// contains arguments. +// GetProcessName - Extracts the process name from the specified +// commandline. // //-------------------------------------------------------------------- -char * GetProcessName(char* processName) +char * GetProcessNameFromCmdLine(char* cmdLine) { - char* retString = processName; + char* retString = cmdLine; std::string procName = ""; - std::string inputString = processName; + std::string inputString = cmdLine; size_t firstSpacePos = inputString.find(' '); if (firstSpacePos != std::string::npos) { @@ -599,11 +598,11 @@ char * GetProcessName(pid_t pid) if(processName != NULL) { - return GetProcessName(processName + 1); // +1 to not include '/' character + return GetProcessNameFromCmdLine(processName + 1); // +1 to not include '/' character } else { - return GetProcessName(stringItr); + return GetProcessNameFromCmdLine(stringItr); } } else From 86baeefd8ec5f0528bc8e5d55e65ed1940578bbd Mon Sep 17 00:00:00 2001 From: Mario Hewardt Date: Mon, 22 Jan 2024 12:53:11 -0800 Subject: [PATCH 4/4] Add DEBUG env variable to build to enable/disable optimizations --- CMakeLists.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d369757..1496e49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,6 +182,13 @@ add_executable(procdump ) target_compile_options(procdump PRIVATE -g -pthread -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Werror -D_GNU_SOURCE -std=c++11) +if (NOT DEFINED ENV{DEBUG}) + message(STATUS "procdump DEBUG disabled. Enabling optimizations.") + add_compile_options(procdump -O2) +else() + message(STATUS "procdump DEBUG enabled. Disabling optimizations.") +endif() + target_include_directories(procdump PUBLIC ${procdump_INC} @@ -210,7 +217,14 @@ add_executable(ProcDumpTestApplication ${procdump_Test}/ProcDumpTestApplication.c ) -target_compile_options(ProcDumpTestApplication PRIVATE -g -pthread -std=gnu99 -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -Werror -O2) +target_compile_options(ProcDumpTestApplication PRIVATE -g -pthread -std=gnu99 -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -Werror) +if (NOT DEFINED ENV{DEBUG}) + message(STATUS "ProcDumpTestApplication DEBUG disabled. Enabling optimizations.") + add_compile_options(ProcDumpTestApplication -O2) +else() + message(STATUS "ProcDumpTestApplication DEBUG enabled. Disabling optimizations.") +endif() + target_include_directories(ProcDumpTestApplication PUBLIC /usr/include