summaryrefslogtreecommitdiff
path: root/src/pal
diff options
context:
space:
mode:
authorMike McLaughlin <mikem@microsoft.com>2019-05-08 00:46:51 -0700
committerGitHub <noreply@github.com>2019-05-08 00:46:51 -0700
commit794f2f89399026246562181bc999a5027fb6583d (patch)
treed87fc6ee11a0b925a678dc5500a42cbc707ea58f /src/pal
parent653e25ec4780cfb7132dcb55bda20dbcc9c2a027 (diff)
downloadcoreclr-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.h8
-rw-r--r--src/pal/src/thread/process.cpp268
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);
+ }
}
/*++