Skip to content

Commit

Permalink
Provide fix for #81093 - "Mono does not emit ProcessExit event on SIG…
Browse files Browse the repository at this point in the history
…TERM" (#100056)

* src/mono/mono/mini/mini-posix.c
  - Add signal handler for SIGTERM

* src/mono/mono/mini/mini-windows.c
  - Add signal handler for SIGTERM
  - Use the correct signal for handler

* 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
  - Set a default exit code before setting the term_signaled variable that gets checked in gc

* 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.
  - Simplify use of exit code now that a default is being set
  - Rename term_signaled to match mono style
  - Remove volatile attribute
  - Move testing of shutdown until after the sem wait

* src/libraries/System.Runtime/tests/System/ExitCodeTests.Unix.cs
  - Re-enable ExitCodeTests for mono

* src/mono/mono/mini/exceptions-amd64.c
  src/mono/mono/mini/exceptions-x86.c
  - Add control event handling for windows

Co-authored-by: Jo Shields <directhex@apebox.org>
  • Loading branch information
nealef and directhex authored Jul 11, 2024
1 parent ddc9d59 commit 5bc0f83
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
10 changes: 10 additions & 0 deletions src/mono/mono/metadata/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <mono/metadata/class-internals.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/runtime.h>
#include <mono/sgen/sgen-conf.h>
#include <mono/sgen/sgen-gc.h>
#include <mono/utils/mono-logger-internals.h>
Expand Down Expand Up @@ -63,6 +64,8 @@ static gboolean gc_disabled;

static gboolean finalizing_root_domain;

extern gboolean mono_term_signaled;

gboolean mono_log_finalizers;
gboolean mono_do_not_finalize;
static volatile gboolean suspend_finalizers;
Expand Down Expand Up @@ -852,6 +855,7 @@ finalizer_thread (gpointer unused)
mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big);

while (!finished) {

/* Wait to be notified that there's at least one
* finaliser to run
*/
Expand All @@ -865,6 +869,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
Expand Down
34 changes: 34 additions & 0 deletions src/mono/mono/mini/exceptions-amd64.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@
#include "mono/utils/mono-tls-inline.h"

#ifdef TARGET_WIN32
#include <windows.h>
static void (*restore_stack) (void);
static MonoW32ExceptionHandler fpe_handler;
static MonoW32ExceptionHandler ill_handler;
static MonoW32ExceptionHandler segv_handler;
static MonoW32ExceptionHandler term_handler = NULL;

extern gboolean mono_term_signaled;

LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter;
void *mono_win_vectored_exception_handle;
Expand Down Expand Up @@ -214,6 +218,31 @@ void win32_seh_cleanup(void)
g_assert (ret);
}

BOOL WINAPI mono_win_ctrl_handler(DWORD fdwCtrlType)
{
switch (fdwCtrlType) {
case CTRL_C_EVENT:
if (term_handler != NULL)
term_handler(0, NULL, NULL);
return TRUE;
break;
case CTRL_CLOSE_EVENT:
return TRUE;
break;
case CTRL_BREAK_EVENT:
return FALSE;
break;
case CTRL_LOGOFF_EVENT:
return FALSE;
break;
case CTRL_SHUTDOWN_EVENT:
return FALSE;
break;
default:
return FALSE;
}
}

void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
{
switch (type) {
Expand All @@ -226,6 +255,11 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
case SIGSEGV:
segv_handler = handler;
break;
case SIGTERM:
term_handler = handler;
if (!SetConsoleCtrlHandler(mono_win_ctrl_handler, TRUE))
fprintf(stderr,"Cannot set control handler\n");
break;
default:
break;
}
Expand Down
31 changes: 31 additions & 0 deletions src/mono/mono/mini/exceptions-x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static void (*restore_stack) (void *);
static MonoW32ExceptionHandler fpe_handler;
static MonoW32ExceptionHandler ill_handler;
static MonoW32ExceptionHandler segv_handler;
static MonoW32ExceptionHandler term_handler = NULL;

LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter;
gpointer mono_win_vectored_exception_handle;
Expand Down Expand Up @@ -260,6 +261,31 @@ void win32_seh_cleanup(void)
RemoveVectoredExceptionHandler (mono_win_vectored_exception_handle);
}

BOOL WINAPI mono_win_ctrl_handler(DWORD fdwCtrlType)
{
switch (fdwCtrlType) {
case CTRL_C_EVENT:
if (term_handler != NULL)
term_handler(0, NULL, NULL);
return TRUE;
break;
case CTRL_CLOSE_EVENT:
return TRUE;
break;
case CTRL_BREAK_EVENT:
return FALSE;
break;
case CTRL_LOGOFF_EVENT:
return FALSE;
break;
case CTRL_SHUTDOWN_EVENT:
return FALSE;
break;
default:
return FALSE;
}
}

void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
{
switch (type) {
Expand All @@ -272,6 +298,11 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
case SIGSEGV:
segv_handler = handler;
break;
case SIGTERM:
term_handler = handler;
if (!SetConsoleCtrlHandler(mono_win_ctrl_handler, TRUE))
fprintf(stderr,"Cannot set control handler\n");
break;
default:
break;
}
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/mini-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const char *mono_build_date;
gboolean mono_do_signal_chaining;
gboolean mono_do_crash_chaining;
int mini_verbose = 0;
gboolean mono_term_signaled = FALSE;

/*
* This flag controls whenever the runtime uses LLVM for JIT compilation, and whenever
Expand Down Expand Up @@ -3758,6 +3759,17 @@ MONO_SIG_HANDLER_FUNC (, mono_crashing_signal_handler)
}
}

MONO_SIG_HANDLER_FUNC (, mono_sigterm_signal_handler)
{
mono_environment_exitcode_set(128+SIGTERM); /* Set default exit code */

mono_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
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,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)
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,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(SIGTERM, mono_sigterm_signal_handler);
if (mini_debug_options.handle_sigint)
win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
#endif
Expand Down

0 comments on commit 5bc0f83

Please sign in to comment.