From 5be9bbf176bce13f8304b9db84ef7657c514bec0 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Wed, 28 Jan 2026 21:47:11 +0000 Subject: [PATCH 1/6] [CoreCLR][Signal] Bump shutdown notif and crashdump before prev handler --- src/coreclr/pal/src/exception/signal.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index b13c286590091e..c235ec0a24df45 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -447,7 +447,14 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t PROCAbort(code, siginfo, context); } } - else if (IsSaSigInfo(action)) + + _ASSERTE(!IsSigDfl(action) && !IsSigIgn(action)); + + PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); + + PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); + + if (IsSaSigInfo(action)) { // Directly call the previous handler. _ASSERTE(action->sa_sigaction != NULL); @@ -459,10 +466,6 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t _ASSERTE(action->sa_handler != NULL); action->sa_handler(code); } - - PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); - - PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); } /*++ From 2e332eed80974fc79bd235d7aa213040307c9b92 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 10 Feb 2026 19:50:28 -0500 Subject: [PATCH 2/6] Revert "[CoreCLR][Signal] Bump shutdown notif and crashdump before prev handler" This reverts commit 5be9bbf176bce13f8304b9db84ef7657c514bec0. --- src/coreclr/pal/src/exception/signal.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index c235ec0a24df45..b13c286590091e 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -447,14 +447,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t PROCAbort(code, siginfo, context); } } - - _ASSERTE(!IsSigDfl(action) && !IsSigIgn(action)); - - PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); - - PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); - - if (IsSaSigInfo(action)) + else if (IsSaSigInfo(action)) { // Directly call the previous handler. _ASSERTE(action->sa_sigaction != NULL); @@ -466,6 +459,10 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t _ASSERTE(action->sa_handler != NULL); action->sa_handler(code); } + + PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); + + PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); } /*++ From 8348deb7e75f659da0182eeba46eb8028584538a Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Wed, 11 Feb 2026 00:56:35 -0500 Subject: [PATCH 3/6] [CoreCLR][Signal] Add config to generate crash dump before invoking previous handler --- src/coreclr/dlls/mscoree/exports.cpp | 22 ++++++++- src/coreclr/pal/inc/pal.h | 5 +++ src/coreclr/pal/src/exception/signal.cpp | 49 +++++++++++++++++++-- src/native/corehost/host_runtime_contract.h | 1 + 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index 1515423445bb32..b38ba86551f630 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -136,7 +136,8 @@ static void ConvertConfigPropertiesToUnicode( LPCWSTR** propertyValuesWRef, BundleProbeFn** bundleProbe, PInvokeOverrideFn** pinvokeOverride, - host_runtime_contract** hostContract) + host_runtime_contract** hostContract, + bool* enableCrashChaining) { LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount]; ASSERTE_ALL_BUILDS(propertyKeysW != nullptr); @@ -181,6 +182,16 @@ static void ConvertConfigPropertiesToUnicode( if (hostContractLocal->pinvoke_override != nullptr) *pinvokeOverride = hostContractLocal->pinvoke_override; } + else if (strcmp(propertyKeys[propertyIndex], HOST_PROPERTY_CRASH_CHAINING) == 0) + { + // Enable crash chaining - generate crash dump before invoking previously registered signal handler. + // This must be processed before PAL initialization. + if (enableCrashChaining != nullptr) + { + *enableCrashChaining = (u16_strcmp(propertyValuesW[propertyIndex], W("1")) == 0 || + u16_strcmp(propertyValuesW[propertyIndex], W("true")) == 0); + } + } } *propertyKeysWRef = propertyKeysW; @@ -246,6 +257,7 @@ int coreclr_initialize( BundleProbeFn* bundleProbe = nullptr; PInvokeOverrideFn* pinvokeOverride = nullptr; host_runtime_contract* hostContract = nullptr; + bool enableCrashChaining = false; #ifdef TARGET_UNIX HostingApiFrameHolder apiFrameHolder(_ReturnAddress()); @@ -259,9 +271,15 @@ int coreclr_initialize( &propertyValuesW, &bundleProbe, &pinvokeOverride, - &hostContract); + &hostContract, + &enableCrashChaining); #ifdef TARGET_UNIX + if (enableCrashChaining) + { + PAL_EnableCrashChaining(); + } + DWORD error = PAL_InitializeCoreCLR(exePath, g_coreclr_embedded); hr = HRESULT_FROM_WIN32(error); diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 5e5ea9173ae6de..1425eb79825099 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -252,6 +252,11 @@ PALAPI PAL_SetCreateDumpCallback( IN PCREATEDUMP_CALLBACK callback); +PALIMPORT +VOID +PALAPI +PAL_EnableCrashChaining(); + PALIMPORT BOOL PALAPI diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index b13c286590091e..bdd4f17a8d4536 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -103,6 +103,8 @@ bool g_registered_signal_handlers = false; #if !HAVE_MACH_EXCEPTIONS bool g_enable_alternate_stack_check = false; #endif // !HAVE_MACH_EXCEPTIONS +// When true, generate crash dump before invoking previously registered signal handler +static bool g_enable_crash_chaining = false; static bool g_registered_sigterm_handler = false; static bool g_registered_activation_handler = false; @@ -133,6 +135,29 @@ const int StackOverflowFlag = 0x40000000; /* public function definitions ************************************************/ +/*++ +Function : + PAL_EnableCrashChaining + + Enables crash chaining. When enabled, crash dumps are generated + before invoking the previously registered signal handler. + +Parameters : + None + + (no return value) + +Note : + Must be called before PAL_InitializeCoreCLR for the setting to take effect. +--*/ +PALIMPORT +VOID +PALAPI +PAL_EnableCrashChaining() +{ + g_enable_crash_chaining = true; +} + /*++ Function : SEHInitializeSignals @@ -161,6 +186,14 @@ BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags) } #endif + CLRConfigNoCache crashChaining = CLRConfigNoCache::Get("EnableCrashChaining", /*noprefix*/ false, &getenv); + if (crashChaining.IsSet()) + { + DWORD value; + if (crashChaining.TryAsInteger(10, value)) + g_enable_crash_chaining = (value != 0); + } + if (flags & PAL_INITIALIZE_REGISTER_SIGNALS) { g_registered_signal_handlers = true; @@ -447,7 +480,15 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t PROCAbort(code, siginfo, context); } } - else if (IsSaSigInfo(action)) + + _ASSERTE(!IsSigDfl(action) && !IsSigIgn(action)); + + if (g_enable_crash_chaining) + { + PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); + } + + if (IsSaSigInfo(action)) { // Directly call the previous handler. _ASSERTE(action->sa_sigaction != NULL); @@ -461,8 +502,10 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t } PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); - - PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); + if (!g_enable_crash_chaining) + { + PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); + } } /*++ diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 558a7093379efa..82d14d0ee6a111 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -23,6 +23,7 @@ #define HOST_PROPERTY_PINVOKE_OVERRIDE "PINVOKE_OVERRIDE" #define HOST_PROPERTY_PLATFORM_RESOURCE_ROOTS "PLATFORM_RESOURCE_ROOTS" #define HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES "TRUSTED_PLATFORM_ASSEMBLIES" +#define HOST_PROPERTY_CRASH_CHAINING "CRASH_CHAINING" // Context passed to get_native_code_data callback struct host_runtime_contract_native_code_context From 628ac91eb62481ea98b560959088d9d4d4b4bcf8 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Wed, 11 Feb 2026 14:16:48 -0500 Subject: [PATCH 4/6] Address feedback: use Configuration knobs instead of early property parsing - Switch from parsing CRASH_CHAINING property before PAL init to using Configuration::GetKnobBooleanValue after InitializeConfigurationKnobs - Add INTERNAL_CrashReportBeforeSignalChaining to clrconfigvalues.h - Rename API to PAL_EnableCrashReportBeforeSignalChaining for clarity - Remove HOST_PROPERTY_CRASH_CHAINING (no longer needed) - Remove CLRConfigNoCache::Get from signal.cpp (use standard config system) --- src/coreclr/dlls/mscoree/exports.cpp | 29 ++++++------------ src/coreclr/inc/clrconfigvalues.h | 1 + src/coreclr/pal/inc/pal.h | 2 +- src/coreclr/pal/src/exception/signal.cpp | 34 ++++++--------------- src/native/corehost/host_runtime_contract.h | 1 - 5 files changed, 20 insertions(+), 47 deletions(-) diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index b38ba86551f630..92a16b91c9b439 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -136,8 +136,7 @@ static void ConvertConfigPropertiesToUnicode( LPCWSTR** propertyValuesWRef, BundleProbeFn** bundleProbe, PInvokeOverrideFn** pinvokeOverride, - host_runtime_contract** hostContract, - bool* enableCrashChaining) + host_runtime_contract** hostContract) { LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount]; ASSERTE_ALL_BUILDS(propertyKeysW != nullptr); @@ -182,16 +181,6 @@ static void ConvertConfigPropertiesToUnicode( if (hostContractLocal->pinvoke_override != nullptr) *pinvokeOverride = hostContractLocal->pinvoke_override; } - else if (strcmp(propertyKeys[propertyIndex], HOST_PROPERTY_CRASH_CHAINING) == 0) - { - // Enable crash chaining - generate crash dump before invoking previously registered signal handler. - // This must be processed before PAL initialization. - if (enableCrashChaining != nullptr) - { - *enableCrashChaining = (u16_strcmp(propertyValuesW[propertyIndex], W("1")) == 0 || - u16_strcmp(propertyValuesW[propertyIndex], W("true")) == 0); - } - } } *propertyKeysWRef = propertyKeysW; @@ -257,7 +246,6 @@ int coreclr_initialize( BundleProbeFn* bundleProbe = nullptr; PInvokeOverrideFn* pinvokeOverride = nullptr; host_runtime_contract* hostContract = nullptr; - bool enableCrashChaining = false; #ifdef TARGET_UNIX HostingApiFrameHolder apiFrameHolder(_ReturnAddress()); @@ -271,15 +259,9 @@ int coreclr_initialize( &propertyValuesW, &bundleProbe, &pinvokeOverride, - &hostContract, - &enableCrashChaining); + &hostContract); #ifdef TARGET_UNIX - if (enableCrashChaining) - { - PAL_EnableCrashChaining(); - } - DWORD error = PAL_InitializeCoreCLR(exePath, g_coreclr_embedded); hr = HRESULT_FROM_WIN32(error); @@ -315,6 +297,13 @@ int coreclr_initialize( // This will take ownership of propertyKeysWTemp and propertyValuesWTemp Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW); +#ifdef TARGET_UNIX + if (Configuration::GetKnobBooleanValue(W("CrashReportBeforeSignalChaining"), CLRConfig::INTERNAL_CrashReportBeforeSignalChaining)) + { + PAL_EnableCrashReportBeforeSignalChaining(); + } +#endif + STARTUP_FLAGS startupFlags; InitializeStartupFlags(&startupFlags); diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 8d2652c6c0fbc8..3aa3ef12ddfc34 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -572,6 +572,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgEnableMiniDump, W("DbgEnableMiniDump"), 0, RETAIL_CONFIG_STRING_INFO(INTERNAL_DbgMiniDumpName, W("DbgMiniDumpName"), "Crash dump name") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgMiniDumpType, W("DbgMiniDumpType"), 0, "Crash dump type: 1 normal, 2 withheap, 3 triage, 4 full") RETAIL_CONFIG_DWORD_INFO(INTERNAL_CreateDumpDiagnostics, W("CreateDumpDiagnostics"), 0, "Enable crash dump generation diagnostic logging") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_CrashReportBeforeSignalChaining, W("CrashReportBeforeSignalChaining"), 0, "Enable crash report generation before chaining to previous signal handler") /// /// R2R diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 1425eb79825099..e812a45c507752 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -255,7 +255,7 @@ PAL_SetCreateDumpCallback( PALIMPORT VOID PALAPI -PAL_EnableCrashChaining(); +PAL_EnableCrashReportBeforeSignalChaining(); PALIMPORT BOOL diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index bdd4f17a8d4536..69049810497924 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -104,7 +104,7 @@ bool g_registered_signal_handlers = false; bool g_enable_alternate_stack_check = false; #endif // !HAVE_MACH_EXCEPTIONS // When true, generate crash dump before invoking previously registered signal handler -static bool g_enable_crash_chaining = false; +static bool g_crash_report_before_signal_chaining = false; static bool g_registered_sigterm_handler = false; static bool g_registered_activation_handler = false; @@ -136,26 +136,18 @@ const int StackOverflowFlag = 0x40000000; /* public function definitions ************************************************/ /*++ -Function : - PAL_EnableCrashChaining - - Enables crash chaining. When enabled, crash dumps are generated - before invoking the previously registered signal handler. - -Parameters : - None - - (no return value) +Function: + PAL_EnableCrashReportBeforeSignalChaining -Note : - Must be called before PAL_InitializeCoreCLR for the setting to take effect. +Abstract: + Enables generating a crash report before the signal is chained to previous handlers. --*/ PALIMPORT VOID PALAPI -PAL_EnableCrashChaining() +PAL_EnableCrashReportBeforeSignalChaining() { - g_enable_crash_chaining = true; + g_crash_report_before_signal_chaining = true; } /*++ @@ -186,14 +178,6 @@ BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags) } #endif - CLRConfigNoCache crashChaining = CLRConfigNoCache::Get("EnableCrashChaining", /*noprefix*/ false, &getenv); - if (crashChaining.IsSet()) - { - DWORD value; - if (crashChaining.TryAsInteger(10, value)) - g_enable_crash_chaining = (value != 0); - } - if (flags & PAL_INITIALIZE_REGISTER_SIGNALS) { g_registered_signal_handlers = true; @@ -483,7 +467,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t _ASSERTE(!IsSigDfl(action) && !IsSigIgn(action)); - if (g_enable_crash_chaining) + if (g_crash_report_before_signal_chaining) { PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); } @@ -502,7 +486,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t } PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); - if (!g_enable_crash_chaining) + if (!g_crash_report_before_signal_chaining) { PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); } diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 82d14d0ee6a111..558a7093379efa 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -23,7 +23,6 @@ #define HOST_PROPERTY_PINVOKE_OVERRIDE "PINVOKE_OVERRIDE" #define HOST_PROPERTY_PLATFORM_RESOURCE_ROOTS "PLATFORM_RESOURCE_ROOTS" #define HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES "TRUSTED_PLATFORM_ASSEMBLIES" -#define HOST_PROPERTY_CRASH_CHAINING "CRASH_CHAINING" // Context passed to get_native_code_data callback struct host_runtime_contract_native_code_context From 974f3e611a4bc3e7466c2c0ee2d465cc8e88f068 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Thu, 12 Feb 2026 14:22:48 -0500 Subject: [PATCH 5/6] Address feedback - Rename configuration key for standardization - Allow PROCNotifyProcessShutdown when crash reporting before signal chaining - Conform to PAL formatting --- src/coreclr/dlls/mscoree/exports.cpp | 2 +- src/coreclr/pal/inc/pal.h | 3 ++- src/coreclr/pal/src/exception/signal.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index 92a16b91c9b439..053993ad1918a3 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -298,7 +298,7 @@ int coreclr_initialize( Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW); #ifdef TARGET_UNIX - if (Configuration::GetKnobBooleanValue(W("CrashReportBeforeSignalChaining"), CLRConfig::INTERNAL_CrashReportBeforeSignalChaining)) + if (Configuration::GetKnobBooleanValue(W("System.Runtime.CrashReportBeforeSignalChaining"), CLRConfig::INTERNAL_CrashReportBeforeSignalChaining)) { PAL_EnableCrashReportBeforeSignalChaining(); } diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index e812a45c507752..bf820a7531dc15 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -255,7 +255,8 @@ PAL_SetCreateDumpCallback( PALIMPORT VOID PALAPI -PAL_EnableCrashReportBeforeSignalChaining(); +PAL_EnableCrashReportBeforeSignalChaining( + void); PALIMPORT BOOL diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index 69049810497924..6a3b6f52f0445f 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -145,7 +145,8 @@ const int StackOverflowFlag = 0x40000000; PALIMPORT VOID PALAPI -PAL_EnableCrashReportBeforeSignalChaining() +PAL_EnableCrashReportBeforeSignalChaining( + void) { g_crash_report_before_signal_chaining = true; } @@ -469,6 +470,7 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t if (g_crash_report_before_signal_chaining) { + PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); } @@ -485,9 +487,9 @@ static void invoke_previous_action(struct sigaction* action, int code, siginfo_t action->sa_handler(code); } - PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); if (!g_crash_report_before_signal_chaining) { + PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context)); PROCCreateCrashDumpIfEnabled(code, siginfo, context, true); } } From 438c18dd96cafacff6594f0fea71901cdb42316d Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Thu, 12 Feb 2026 14:25:14 -0500 Subject: [PATCH 6/6] [Android CoreCLR] Default to generating crash report before signal chaining --- src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c index fed141345b8d25..19d11ad3fb62fb 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c @@ -190,6 +190,7 @@ mono_droid_runtime_init (const char* executable) #ifdef DIAGNOSTIC_PORTS setenv ("DOTNET_DiagnosticPorts", DIAGNOSTIC_PORTS, true); #endif + setenv ("DOTNET_CrashReportBeforeSignalChaining", "1", true); if (bundle_executable_path(executable, g_bundle_path, &g_executable_path) < 0) {