Skip to content

Commit d778a6a

Browse files
mdh1418Copilot
andauthored
[Diagnostics] Add in-proc crash report watchdog (#128281)
Adds a watchdog for the in-proc crash report generation so a hung crash reporter cannot leave the process stuck indefinitely. The in-proc crash reporter runs while the process is already handling a fatal signal. If the reporter hangs, OS-level watchdogs are not reliable across all relevant app locations, especially worker/background-thread crashes. This bounds reporter execution time and ensures the process eventually terminates instead of remaining stuck. The watchdog is initialized outside the crash path, uses a pipe-backed notification channel, and keeps the crash-reporting path limited to async-signal-safe `write()` calls. If report generation starts but does not finish before the configured timeout, the watchdog aborts the process with SIGABRT. - Adds `inproccrashreportwatchdog.{h,cpp}`. - Arms the watchdog when `InProcCrashReporter::CreateReport()` begins and disarms it when report generation exits. - Uses a detached watchdog thread plus a nonblocking pipe instead of semaphores for POSIX compatibility. - Blocks fatal signals on the watchdog thread so process-directed crash signals do not land there. - Adds `DOTNET_CrashReportTimeoutSeconds`. - Default: `30` - `0` disables the watchdog for diagnostics/debugging. - Keeps watchdog initialization best-effort; if initialization fails, crash reporting proceeds without the watchdog. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a82b355 commit d778a6a

7 files changed

Lines changed: 543 additions & 0 deletions

File tree

src/coreclr/debug/crashreport/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ set(CRASHREPORT_SOURCES
55
signalsafejsonwriter.cpp
66
signalsafeconsolewriter.cpp
77
inproccrashreporter.cpp
8+
inproccrashreportwatchdog.cpp
89
)
910

1011
add_library(inproccrashreport OBJECT ${CRASHREPORT_SOURCES})
12+
target_include_directories(inproccrashreport PRIVATE ${CLR_DIR}/pal/src/include)
1113

1214
target_sources(coreclrpal PRIVATE $<TARGET_OBJECTS:inproccrashreport>)

src/coreclr/debug/crashreport/inproccrashreporter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// Streams a createdump-shaped JSON skeleton to a crashreport.json file.
77

88
#include "inproccrashreporter.h"
9+
#include "inproccrashreportwatchdog.h"
910
#include "signalsafeconsolewriter.h"
1011
#include "signalsafejsonwriter.h"
1112
#include "signalsafeformatter.h"
@@ -15,6 +16,7 @@
1516

1617
#include <fcntl.h>
1718
#include <errno.h>
19+
#include <stdlib.h>
1820
#include <new>
1921
#include <unistd.h>
2022
#include <string.h>
@@ -608,6 +610,7 @@ InProcCrashReporter::CreateReport(
608610
{
609611
return;
610612
}
613+
CrashReportWatchdogScope watchdogScope;
611614

612615
m_reportFilePath[0] = '\0';
613616
// The JSON file sink is only enabled when DbgMiniDumpName supplied a
@@ -746,6 +749,8 @@ InProcCrashReporter::Initialize(
746749
m_stackOverflowTrace.available = 0;
747750
CrashReportHelpers::CopyString(m_reportPath, sizeof(m_reportPath), settings.reportPath);
748751

752+
(void)CrashReportWatchdog::TryInitialize(settings.timeoutSeconds);
753+
749754
m_processName[0] = '\0';
750755
#if defined(__ANDROID__)
751756
// On Android every app forks from the Zygote, so /proc/self/exe always

src/coreclr/debug/crashreport/inproccrashreporter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ using InProcCrashReportModuleInfoCallback = bool (*)(
7474
struct InProcCrashReporterSettings
7575
{
7676
const char* reportPath;
77+
int timeoutSeconds;
7778
InProcCrashReportIsManagedThreadCallback isManagedThreadCallback;
7879
InProcCrashReportWalkStackCallback walkStackCallback;
7980
InProcCrashReportEnumerateThreadsCallback enumerateThreadsCallback;

0 commit comments

Comments
 (0)