diff options
author | Mike McLaughlin <mikem@microsoft.com> | 2019-05-08 00:46:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-08 00:46:51 -0700 |
commit | 794f2f89399026246562181bc999a5027fb6583d (patch) | |
tree | d87fc6ee11a0b925a678dc5500a42cbc707ea58f /src/pal | |
parent | 653e25ec4780cfb7132dcb55bda20dbcc9c2a027 (diff) | |
download | coreclr-794f2f89399026246562181bc999a5027fb6583d.tar.gz coreclr-794f2f89399026246562181bc999a5027fb6583d.tar.bz2 coreclr-794f2f89399026246562181bc999a5027fb6583d.zip |
Add generate crash dump command to diagnostics server (#24460)
Add the DiagnosticProtocolHelper class to deserialize and dispatch
the new GenerateCoreDump command.
Refactor the PAL createdump launch on unhandled exception code to
used by a new PAL_GenerateCoreDump method that doesn't depend on
the complus dump environment variables.
Changed the "full" createdump not to include the uncommitted pages and
removed the "add module metadata" workaround for SOS clrstack !UNKNOWN
problem now that is fixed in SOS (crashinfo.cpp).
Diffstat (limited to 'src/pal')
-rw-r--r-- | src/pal/inc/pal.h | 8 | ||||
-rw-r--r-- | src/pal/src/thread/process.cpp | 268 |
2 files changed, 189 insertions, 87 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index f4a726e89f..a2b15f3d12 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -450,6 +450,14 @@ PALAPI PAL_SetShutdownCallback( IN PSHUTDOWN_CALLBACK callback); +PALIMPORT +BOOL +PALAPI +PAL_GenerateCoreDump( + IN LPCSTR dumpName, + IN INT dumpType, + IN BOOL diag); + typedef VOID (*PPAL_STARTUP_CALLBACK)( char *modulePath, HMODULE hModule, diff --git a/src/pal/src/thread/process.cpp b/src/pal/src/thread/process.cpp index 445b75cc68..8b9fec421b 100644 --- a/src/pal/src/thread/process.cpp +++ b/src/pal/src/thread/process.cpp @@ -3206,119 +3206,107 @@ PROCNotifyProcessShutdown() /*++ Function - PROCAbortInitialize() + PROCBuildCreateDumpCommandLine Abstract - Initialize the process abort crash dump program file path and - name. Doing all of this ahead of time so nothing is allocated - or copied in PROCAbort/signal handler. + Builds the createdump command line from the arguments. Return TRUE - succeeds, FALSE - fails --*/ BOOL -PROCAbortInitialize() +PROCBuildCreateDumpCommandLine(const char** argv, char* dumpName, char* dumpType, BOOL diag) { - char* enabled = getenv("COMPlus_DbgEnableMiniDump"); - if (enabled != nullptr && _stricmp(enabled, "1") == 0) + if (g_szCoreCLRPath == nullptr) { - if (g_szCoreCLRPath == nullptr) - { - return FALSE; - } - const char* DumpGeneratorName = "createdump"; - int programLen = strlen(g_szCoreCLRPath) + strlen(DumpGeneratorName) + 1; - char* program = (char*)InternalMalloc(programLen); - if (program == nullptr) - { - return FALSE; - } - if (strcpy_s(program, programLen, g_szCoreCLRPath) != SAFECRT_SUCCESS) - { - return FALSE; - } - char *last = strrchr(program, '/'); - if (last != nullptr) - { - *(last + 1) = '\0'; - } - else - { - program[0] = '\0'; - } - if (strcat_s(program, programLen, DumpGeneratorName) != SAFECRT_SUCCESS) + return FALSE; + } + const char* DumpGeneratorName = "createdump"; + int programLen = strlen(g_szCoreCLRPath) + strlen(DumpGeneratorName) + 1; + char* program = (char*)InternalMalloc(programLen); + if (program == nullptr) + { + return FALSE; + } + if (strcpy_s(program, programLen, g_szCoreCLRPath) != SAFECRT_SUCCESS) + { + return FALSE; + } + char *last = strrchr(program, '/'); + if (last != nullptr) + { + *(last + 1) = '\0'; + } + else + { + program[0] = '\0'; + } + if (strcat_s(program, programLen, DumpGeneratorName) != SAFECRT_SUCCESS) + { + return FALSE; + } + char* pidarg = (char*)InternalMalloc(128); + if (pidarg == nullptr) + { + return FALSE; + } + if (sprintf_s(pidarg, 128, "%d", gPID) == -1) + { + return FALSE; + } + *argv++ = program; + + if (dumpName != nullptr) + { + *argv++ = "--name"; + *argv++ = dumpName; + } + + if (dumpType != nullptr) + { + if (strcmp(dumpType, "1") == 0) { - return FALSE; + *argv++ = "--normal"; } - char* pidarg = (char*)InternalMalloc(128); - if (pidarg == nullptr) + else if (strcmp(dumpType, "2") == 0) { - return FALSE; + *argv++ = "--withheap"; } - if (sprintf_s(pidarg, 128, "%d", gPID) == -1) + else if (strcmp(dumpType, "3") == 0) { - return FALSE; + *argv++ = "--triage"; } - const char** argv = (const char**)g_argvCreateDump; - *argv++ = program; - - char* envvar = getenv("COMPlus_DbgMiniDumpName"); - if (envvar != nullptr) + else if (strcmp(dumpType, "4") == 0) { - *argv++ = "--name"; - *argv++ = envvar; + *argv++ = "--full"; } + } - envvar = getenv("COMPlus_DbgMiniDumpType"); - if (envvar != nullptr) - { - if (strcmp(envvar, "1") == 0) - { - *argv++ = "--normal"; - } - else if (strcmp(envvar, "2") == 0) - { - *argv++ = "--withheap"; - } - else if (strcmp(envvar, "3") == 0) - { - *argv++ = "--triage"; - } - else if (strcmp(envvar, "4") == 0) - { - *argv++ = "--full"; - } - } + if (diag) + { + *argv++ = "--diag"; + } - envvar = getenv("COMPlus_CreateDumpDiagnostics"); - if (envvar != nullptr && strcmp(envvar, "1") == 0) - { - *argv++ = "--diag"; - } + *argv++ = pidarg; + *argv = nullptr; - *argv++ = pidarg; - *argv = nullptr; - } return TRUE; } /*++ Function: - PROCCreateCrashDumpIfEnabled + PROCCreateCrashDump - Creates crash dump of the process (if enabled). Can be - called from the unhandled native exception handler. + Creates crash dump of the process. Can be called from the + unhandled native exception handler. (no return value) --*/ -VOID -PROCCreateCrashDumpIfEnabled() +BOOL +PROCCreateCrashDump(char** argv) { #if HAVE_PRCTL_H && HAVE_PR_SET_PTRACER - // If enabled, launch the create minidump utility and wait until it completes - if (g_argvCreateDump[0] == nullptr) - return; // Fork the core dump child process. pid_t childpid = fork(); @@ -3326,14 +3314,16 @@ PROCCreateCrashDumpIfEnabled() // If error, write an error to trace log and abort if (childpid == -1) { - ERROR("PROCAbort: fork() FAILED %d (%s)\n", errno, strerror(errno)); + ERROR("PROCCreateCrashDump: fork() FAILED %d (%s)\n", errno, strerror(errno)); + return false; } else if (childpid == 0) { // Child process - if (execve(g_argvCreateDump[0], g_argvCreateDump, palEnvironment) == -1) + if (execve(argv[0], argv, palEnvironment) == -1) { - ERROR("PROCAbort: execve FAILED %d (%s)\n", errno, strerror(errno)); + ERROR("PPROCCreateCrashDump: execve FAILED %d (%s)\n", errno, strerror(errno)); + return false; } } else @@ -3341,18 +3331,122 @@ PROCCreateCrashDumpIfEnabled() // Gives the child process permission to use /proc/<pid>/mem and ptrace if (prctl(PR_SET_PTRACER, childpid, 0, 0, 0) == -1) { - ERROR("PROCAbort: prctl() FAILED %d (%s)\n", errno, strerror(errno)); + ERROR("PPROCCreateCrashDump: prctl() FAILED %d (%s)\n", errno, strerror(errno)); + return false; } // Parent waits until the child process is done - int wstatus; + int wstatus = 0; int result = waitpid(childpid, &wstatus, 0); if (result != childpid) { - ERROR("PROCAbort: waitpid FAILED result %d wstatus %d errno %d (%s)\n", + ERROR("PPROCCreateCrashDump: waitpid FAILED result %d wstatus %d errno %d (%s)\n", result, wstatus, errno, strerror(errno)); + return false; } + return !WIFEXITED(wstatus) || WEXITSTATUS(wstatus) == 0; } #endif // HAVE_PRCTL_H && HAVE_PR_SET_PTRACER + return true; +} + +/*++ +Function + PROCAbortInitialize() + +Abstract + Initialize the process abort crash dump program file path and + name. Doing all of this ahead of time so nothing is allocated + or copied in PROCAbort/signal handler. + +Return + TRUE - succeeds, FALSE - fails + +--*/ +BOOL +PROCAbortInitialize() +{ + char* enabled = getenv("COMPlus_DbgEnableMiniDump"); + if (enabled != nullptr && _stricmp(enabled, "1") == 0) + { + char* dumpName = getenv("COMPlus_DbgMiniDumpName"); + char* dumpType = getenv("COMPlus_DbgMiniDumpType"); + char* diagStr = getenv("COMPlus_CreateDumpDiagnostics"); + BOOL diag = diagStr != nullptr && strcmp(diagStr, "1") == 0; + + if (!PROCBuildCreateDumpCommandLine((const char **)g_argvCreateDump, dumpName, dumpType, diag)) + { + return FALSE; + } + } + return TRUE; +} + +/*++ +Function: + PAL_GenerateCoreDump + +Abstract: + Public entry point to create a crash dump of the process. + +Parameters: + dumpName + dumpType: + Normal = 1, + WithHeap = 2, + Triage = 3, + Full = 4 + diag + true - log createdump diagnostics to console + +Return: + TRUE success + FALSE failed +--*/ +BOOL +PAL_GenerateCoreDump( + LPCSTR dumpName, + INT dumpType, + BOOL diag) +{ + char* argvCreateDump[8] = { nullptr }; + char dumpTypeStr[16]; + + if (dumpType < 1 || dumpType > 4) + { + return FALSE; + } + if (dumpName != nullptr && dumpName[0] == '\0') + { + dumpName = nullptr; + } + if (_itoa_s(dumpType, dumpTypeStr, sizeof(dumpTypeStr), 10) != 0) + { + return FALSE; + } + if (!PROCBuildCreateDumpCommandLine((const char **)argvCreateDump, (char*)dumpName, dumpTypeStr, diag)) + { + return FALSE; + } + return PROCCreateCrashDump(argvCreateDump); +} + +/*++ +Function: + PROCCreateCrashDumpIfEnabled + + Creates crash dump of the process (if enabled). Can be + called from the unhandled native exception handler. + +(no return value) +--*/ +VOID +PROCCreateCrashDumpIfEnabled() +{ + // If enabled, launch the create minidump utility and wait until it completes + if (g_argvCreateDump[0] != nullptr) + { + PROCCreateCrashDump(g_argvCreateDump); + } } /*++ |