Skip to content

Commit

Permalink
Serialize createdump core dump generation
Browse files Browse the repository at this point in the history
Only allow one thread at a time to generate a core dump.

Issue: dotnet#82989
  • Loading branch information
mikem8361 committed Aug 2, 2023
1 parent a743d60 commit 8c23f74
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/coreclr/pal/src/exception/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t

PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

PROCCreateCrashDumpIfEnabled(code, siginfo);
PROCCreateCrashDumpIfEnabled(code, siginfo, true);
}

/*++
Expand Down Expand Up @@ -746,7 +746,7 @@ static void sigterm_handler(int code, siginfo_t *siginfo, void *context)
DWORD val = 0;
if (enableDumpOnSigTerm.IsSet() && enableDumpOnSigTerm.TryAsInteger(10, val) && val == 1)
{
PROCCreateCrashDumpIfEnabled(code, siginfo);
PROCCreateCrashDumpIfEnabled(code, siginfo, false);
}
// g_pSynchronizationManager shouldn't be null if PAL is initialized.
_ASSERTE(g_pSynchronizationManager != nullptr);
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/pal/src/include/pal/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,12 @@ VOID PROCNotifyProcessShutdown(bool isExecutingOnAltStack = false);
Parameters:
signal - POSIX signal number
siginfo - POSIX signal info or nullptr
serialize - allow only one thread to generate core dump
(no return value)
--*/
VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo);
VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize);

/*++
Function:
Expand Down
56 changes: 52 additions & 4 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ LPWSTR g_lpwstrAppDir = NULL;
// Thread ID of thread that has started the ExitProcess process
Volatile<LONG> terminator = 0;

// Id of thread generating a core dump
Volatile<LONG> g_crashingThreadId = 0;

// Process and session ID of this process.
DWORD gPID = (DWORD) -1;
DWORD gSID = (DWORD) -1;
Expand Down Expand Up @@ -2178,7 +2181,8 @@ PROCBuildCreateDumpCommandLine(
Creates crash dump of the process. Can be called from the
unhandled native exception handler.
(no return value)
Return:
TRUE - succeeds, FALSE - fails
--*/
BOOL
PROCCreateCrashDump(
Expand Down Expand Up @@ -2295,6 +2299,41 @@ PROCCreateCrashDump(
return true;
}

/*++
Function:
PROCSerializedCreateCrashDump
Creates crash dump of the process. Only allows one thread to generate the
core dump. Can be called from the unhandled native exception handler.
Return:
nothing
--*/
VOID
PROCSerializedCreateCrashDump(
std::vector<const char*>& argv,
LPSTR errorMessageBuffer,
INT cbErrorMessageBuffer)
{
_ASSERTE(argv.size() > 0);
_ASSERTE(errorMessageBuffer == nullptr || cbErrorMessageBuffer > 0);

size_t currentThreadId = THREADSilentGetCurrentThreadId();
size_t previousThreadId = InterlockedCompareExchange(&g_crashingThreadId, currentThreadId, 0);
if (previousThreadId == 0)
{
PROCCreateCrashDump(argv, errorMessageBuffer, cbErrorMessageBuffer);
}
else
{
// Should never reenter or recurse
_ASSERTE(previousThreadId != currentThreadId)

// The first thread generates the crash info and any other threads are blocked
Sleep(INFINITE);
}
}

/*++
Function
PROCAbortInitialize()
Expand Down Expand Up @@ -2429,11 +2468,13 @@ PAL_GenerateCoreDump(
Parameters:
signal - POSIX signal number
siginfo - POSIX signal info or nullptr
serialize - allow only one thread to generate core dump
(no return value)
--*/
VOID
PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo)
PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize)
{
// If enabled, launch the create minidump utility and wait until it completes
if (!g_argvCreateDump.empty())
Expand Down Expand Up @@ -2491,7 +2532,14 @@ PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo)
argv.push_back(nullptr);
}

PROCCreateCrashDump(argv, nullptr, 0);
if (serialize)
{
PROCSerializedCreateCrashDump(argv, nullptr, 0);
}
else
{
PROCCreateCrashDump(argv, nullptr, 0);
}

free(signalArg);
free(crashThreadArg);
Expand Down Expand Up @@ -2520,7 +2568,7 @@ PROCAbort(int signal, siginfo_t* siginfo)
// Do any shutdown cleanup before aborting or creating a core dump
PROCNotifyProcessShutdown();

PROCCreateCrashDumpIfEnabled(signal, siginfo);
PROCCreateCrashDumpIfEnabled(signal, siginfo, true);

// Restore all signals; the SIGABORT handler to prevent recursion and
// the others to prevent multiple core dumps from being generated.
Expand Down

0 comments on commit 8c23f74

Please sign in to comment.