{
if (signalRestarts)
{
+ // Shutdown and create the core dump before we restore the signal to the default handler.
+ PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));
+
+ PROCCreateCrashDumpIfEnabled(code, siginfo, true);
+
// Restore the original and restart h/w exception.
restore_signal(code, action);
+
+ return;
}
else
{
PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));
- PROCCreateCrashDumpIfEnabled(code, siginfo);
+ PROCCreateCrashDumpIfEnabled(code, siginfo, true);
}
/*++
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);
// 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;
Update: [TODO] PROCSuspendOtherThreads has been removed. Can this
code be changed? */
WARN("termination already started from another thread; blocking.\n");
- poll(NULL, 0, INFTIM);
+ while (true)
+ {
+ poll(NULL, 0, INFTIM);
+ }
}
/* ExitProcess may be called even if PAL is not initialized.
Function:
PROCCreateCrashDump
- Creates crash dump of the process. Can be called from the
- unhandled native exception handler.
+ Creates crash dump of the process. Can be called from the unhandled
+ native exception handler. Allows only one thread to generate the core
+ dump if serialize is true.
-(no return value)
+Return:
+ TRUE - succeeds, FALSE - fails
--*/
BOOL
PROCCreateCrashDump(
std::vector<const char*>& argv,
LPSTR errorMessageBuffer,
- INT cbErrorMessageBuffer)
+ INT cbErrorMessageBuffer,
+ bool serialize)
{
_ASSERTE(argv.size() > 0);
_ASSERTE(errorMessageBuffer == nullptr || cbErrorMessageBuffer > 0);
+ if (serialize)
+ {
+ size_t currentThreadId = THREADSilentGetCurrentThreadId();
+ size_t previousThreadId = InterlockedCompareExchange(&g_crashingThreadId, currentThreadId, 0);
+ if (previousThreadId != 0)
+ {
+ // Should never reenter or recurse
+ _ASSERTE(previousThreadId != currentThreadId);
+
+ // The first thread generates the crash info and any other threads are blocked
+ while (true)
+ {
+ poll(NULL, 0, INFTIM);
+ }
+ }
+ }
+
int pipe_descs[2];
if (pipe(pipe_descs) == -1)
{
BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, dumpName, nullptr, dumpType, flags);
if (result)
{
- result = PROCCreateCrashDump(argvCreateDump, errorMessageBuffer, cbErrorMessageBuffer);
+ result = PROCCreateCrashDump(argvCreateDump, errorMessageBuffer, cbErrorMessageBuffer, false);
}
free(program);
free(pidarg);
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())
argv.push_back(nullptr);
}
- PROCCreateCrashDump(argv, nullptr, 0);
+ PROCCreateCrashDump(argv, nullptr, 0, serialize);
free(signalArg);
free(crashThreadArg);
// 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.
TerminateProcess won't call DllMain, so there's no danger to get
caught in an infinite loop */
WARN("termination already started from another thread; blocking.\n");
- poll(NULL, 0, INFTIM);
+ while (true)
+ {
+ poll(NULL, 0, INFTIM);
+ }
}
/* Try to lock the initialization count to prevent multiple threads from