Skip to content

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM" #100056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
Copy link
Member

@kg kg Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a new handler, so if win32_seh_set_handler was previously called to install a different term_handler, shouldn't we uninstall the old one first?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, i misread, but i think this would add a copy of our handler each time you set a term handler, so we might end up with 3 copies of the same one installed unless the kernel removes duplicates. the docs don't say whether it does

if an application calls AllocConsole or AttachConsole this handler will get uninstalled, but that's probably fine to consider as a 'don't do that' problem

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
Loading