From c07259edbb3cac8ba4f80c771b515c2f54af9312 Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Wed, 1 Mar 2023 05:29:59 +0000 Subject: [PATCH 1/6] Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM" * src/mono/mono/mini/mini-posix.c - Add signal handler for SIGTERM * src/mono/mono/mini/mini-windows.c - Add signal handler for SIGTERM * src/mono/mono/mini/mini-runtime.c - Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread * src/mono/mono/mini/mini-runtime.h - Define prototype for mono_sigterm_signal_handler() * src/mono/mono/metadata/gc.c - Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown(). - Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128. --- src/mono/mono/metadata/gc.c | 14 ++++++++++++++ src/mono/mono/mini/mini-posix.c | 2 ++ src/mono/mono/mini/mini-runtime.c | 10 ++++++++++ src/mono/mono/mini/mini-runtime.h | 1 + src/mono/mono/mini/mini-windows.c | 1 + 5 files changed, 28 insertions(+) diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index f5f74cfd5073c9..1ab78bcf275771 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,8 @@ static gboolean gc_disabled; static gboolean finalizing_root_domain; +extern volatile gboolean term_signaled; + gboolean mono_log_finalizers; gboolean mono_do_not_finalize; static volatile gboolean suspend_finalizers; @@ -879,6 +882,17 @@ finalizer_thread (gpointer unused) mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big); while (!finished) { + + /* Just in case we've received a SIGTERM */ + if (term_signaled) { + int ec = mono_environment_exitcode_get(); + mono_runtime_try_shutdown(); + if (ec == 0) + exit(128+SIGTERM); + else + exit(ec); + } + /* Wait to be notified that there's at least one * finaliser to run */ diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index be8f83d396872d..3f866b5ec73fc1 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -390,6 +390,8 @@ mono_runtime_posix_install_handlers (void) sigaddset (&signal_set, SIGFPE); add_signal_handler (SIGQUIT, sigquit_signal_handler, SA_RESTART); sigaddset (&signal_set, SIGQUIT); + add_signal_handler (SIGTERM, mono_sigterm_signal_handler, SA_RESTART); + sigaddset (&signal_set, SIGTERM); add_signal_handler (SIGILL, mono_crashing_signal_handler, 0); sigaddset (&signal_set, SIGILL); add_signal_handler (SIGBUS, mono_sigsegv_signal_handler, 0); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index cd7117dde4143e..3a489889576efb 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -118,6 +118,7 @@ const char *mono_build_date; gboolean mono_do_signal_chaining; gboolean mono_do_crash_chaining; int mini_verbose = 0; +gboolean term_signaled = FALSE; /* * This flag controls whenever the runtime uses LLVM for JIT compilation, and whenever @@ -3628,6 +3629,15 @@ MONO_SIG_HANDLER_FUNC (, mono_crashing_signal_handler) } } +MONO_SIG_HANDLER_FUNC (, mono_sigterm_signal_handler) +{ + term_signaled = TRUE; + + mono_gc_finalize_notify (); + + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); +} + #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32) #define HAVE_SIG_INFO diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 16299ff4020527..09018b9333fd8f 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -671,6 +671,7 @@ void MONO_SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) ; void MONO_SIG_HANDLER_SIGNATURE (mono_crashing_signal_handler) ; void MONO_SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler); void MONO_SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) ; +void MONO_SIG_HANDLER_SIGNATURE (mono_sigterm_signal_handler) ; gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal); #if defined (HOST_WASM) diff --git a/src/mono/mono/mini/mini-windows.c b/src/mono/mono/mini/mini-windows.c index c678f4c4594c45..4d7a02b7cb8b85 100644 --- a/src/mono/mono/mini/mini-windows.c +++ b/src/mono/mono/mini/mini-windows.c @@ -189,6 +189,7 @@ mono_runtime_install_handlers (void) win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler); win32_seh_set_handler(SIGILL, mono_crashing_signal_handler); win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler); + win32_seh_set_handler(SIGSEGV, mono_sigterm_signal_handler); if (mini_debug_options.handle_sigint) win32_seh_set_handler(SIGINT, mono_sigint_signal_handler); #endif From 9ac0c3b9ce60655ac787d5f33224800abf044e32 Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Mon, 13 Mar 2023 23:20:03 +0000 Subject: [PATCH 2/6] * src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs - Re-enable ExitCodeTests for mono --- src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs b/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs index 9fd7ab4f461a98..bd7cf68e87c366 100644 --- a/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs +++ b/src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs @@ -16,7 +16,6 @@ public class ExitCodeTests private static extern int kill(int pid, int sig); [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/31656", TestRuntimes.Mono)] [InlineData(null)] [InlineData(0)] [InlineData(42)] From 98eeadfe280a1ffd9f1e3214df033f52a033845a Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Tue, 14 Mar 2023 04:19:41 +0000 Subject: [PATCH 3/6] * src/mono/mono/mini/mini-runtime.c - Set a default exit code before starting the SIGTERM processing --- src/mono/mono/mini/mini-runtime.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 3a489889576efb..7de28554c649b2 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -3633,7 +3633,9 @@ MONO_SIG_HANDLER_FUNC (, mono_sigterm_signal_handler) { term_signaled = TRUE; - mono_gc_finalize_notify (); + mono_environment_exitcode_set(128+SIGTERM); /* Set default exit code */ + + mono_gc_finalize_notify (); mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } From 38b5e87e68d76a53ede7784538e973add1d8770f Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Tue, 14 Mar 2023 04:29:42 +0000 Subject: [PATCH 4/6] * src/mono/mono/mini/mini-runtime.c - Set a default exit code before setting the term_signaled variable that gets checked in gc --- src/mono/mono/mini/mini-runtime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 7de28554c649b2..464d6396b55cf9 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -3631,10 +3631,10 @@ MONO_SIG_HANDLER_FUNC (, mono_crashing_signal_handler) MONO_SIG_HANDLER_FUNC (, mono_sigterm_signal_handler) { - term_signaled = TRUE; - mono_environment_exitcode_set(128+SIGTERM); /* Set default exit code */ + term_signaled = TRUE; + mono_gc_finalize_notify (); mono_chain_signal (MONO_SIG_HANDLER_PARAMS); From 3adb5d646646c4cfe3a9dcd66572de9910c524ba Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Tue, 14 Mar 2023 04:32:18 +0000 Subject: [PATCH 5/6] * src/mono/mono/metadata/gc.c - Simplify use of exit code now that a default is being set --- src/mono/mono/metadata/gc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index 1ab78bcf275771..0b015da93e416c 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -885,12 +885,8 @@ finalizer_thread (gpointer unused) /* Just in case we've received a SIGTERM */ if (term_signaled) { - int ec = mono_environment_exitcode_get(); mono_runtime_try_shutdown(); - if (ec == 0) - exit(128+SIGTERM); - else - exit(ec); + exit(mono_environment_exitcode_get()); } /* Wait to be notified that there's at least one From bd9326be47b5168d5ca8157d09f1b2be8be703ee Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Wed, 15 Mar 2023 02:42:44 +0000 Subject: [PATCH 6/6] * src/mono/mono/metadata/gc.c - Rename term_signaled to match mono style - Remove volatile attribute - Move testing of shutdown until after the sem wait * src/mono/mono/mini/mini-runtime.c - Rename term_signaled to mono_term_signaled * src/mono/mono/mini/mini-windows.c - Use the correct signal for handler --- src/mono/mono/metadata/gc.c | 14 +++++++------- src/mono/mono/mini/mini-runtime.c | 4 ++-- src/mono/mono/mini/mini-windows.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index 0b015da93e416c..e1495c70729a33 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -64,7 +64,7 @@ static gboolean gc_disabled; static gboolean finalizing_root_domain; -extern volatile gboolean term_signaled; +extern gboolean mono_term_signaled; gboolean mono_log_finalizers; gboolean mono_do_not_finalize; @@ -883,12 +883,6 @@ finalizer_thread (gpointer unused) while (!finished) { - /* Just in case we've received a SIGTERM */ - if (term_signaled) { - mono_runtime_try_shutdown(); - exit(mono_environment_exitcode_get()); - } - /* Wait to be notified that there's at least one * finaliser to run */ @@ -902,6 +896,12 @@ finalizer_thread (gpointer unused) } wait = TRUE; + /* Just in case we've received a SIGTERM */ + if (mono_term_signaled) { + mono_runtime_try_shutdown(); + exit(mono_environment_exitcode_get()); + } + mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NONE); /* The Finalizer thread doesn't initialize during creation because base managed diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 464d6396b55cf9..ef5802d13822d6 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -118,7 +118,7 @@ const char *mono_build_date; gboolean mono_do_signal_chaining; gboolean mono_do_crash_chaining; int mini_verbose = 0; -gboolean term_signaled = FALSE; +gboolean mono_term_signaled = FALSE; /* * This flag controls whenever the runtime uses LLVM for JIT compilation, and whenever @@ -3633,7 +3633,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigterm_signal_handler) { mono_environment_exitcode_set(128+SIGTERM); /* Set default exit code */ - term_signaled = TRUE; + mono_term_signaled = TRUE; mono_gc_finalize_notify (); diff --git a/src/mono/mono/mini/mini-windows.c b/src/mono/mono/mini/mini-windows.c index 4d7a02b7cb8b85..744d4fa460e818 100644 --- a/src/mono/mono/mini/mini-windows.c +++ b/src/mono/mono/mini/mini-windows.c @@ -189,7 +189,7 @@ mono_runtime_install_handlers (void) win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler); win32_seh_set_handler(SIGILL, mono_crashing_signal_handler); win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler); - win32_seh_set_handler(SIGSEGV, mono_sigterm_signal_handler); + win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler); if (mini_debug_options.handle_sigint) win32_seh_set_handler(SIGINT, mono_sigint_signal_handler); #endif