Skip to content

Commit

Permalink
[mono] Chain SIGSEGV native crashes to the default SIGSEGV handler (
Browse files Browse the repository at this point in the history
dotnet#110741)

* Consider SIG_DFL handlers for chaining SIGSEGV signals
  • Loading branch information
ivanpovazan authored Dec 20, 2024
1 parent 5e38bb1 commit aa190d6
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 5 deletions.
34 changes: 31 additions & 3 deletions src/mono/mono/mini/mini-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,15 @@ save_old_signal_handler (int signo, struct sigaction *old_action)
*
* Call the original signal handler for the signal given by the arguments, which
* should be the same as for a signal handler. Returns TRUE if the original handler
* was called, false otherwise.
* was called, false otherwise. NOTE: sigaction.sa_handler == SIG_DFL handlers are not considered.
*/
gboolean
MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
{
int signal = MONO_SIG_HANDLER_GET_SIGNO ();
struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (signal);

// Ignores chaining to default signal handlers i.e. when saved_handler->sa_handler == SIG_DFL
if (saved_handler && saved_handler->sa_handler) {
if (!(saved_handler->sa_flags & SA_SIGINFO)) {
saved_handler->sa_handler (signal);
Expand All @@ -209,6 +210,27 @@ MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
return FALSE;
}


/*
* mono_chain_signal_to_default_sigsegv_handler:
*
* Call the original SIGSEGV signal handler in cases when the original handler is
* sigaction.sa_handler == SIG_DFL. This is used to propagate the crash to the OS.
*/
void
mono_chain_signal_to_default_sigsegv_handler (void)
{
struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (SIGSEGV);

if (saved_handler && saved_handler->sa_handler == SIG_DFL) {
sigaction (SIGSEGV, saved_handler, NULL);
raise (SIGSEGV);
} else {
g_async_safe_printf ("\nFailed to chain SIGSEGV signal to the default handler.\n");
}
}


MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
{
MonoJitInfo *ji = NULL;
Expand Down Expand Up @@ -348,8 +370,14 @@ add_signal_handler (int signo, MonoSignalHandler handler, int flags)

/* if there was already a handler in place for this signal, store it */
if (! (previous_sa.sa_flags & SA_SIGINFO) &&
(SIG_DFL == previous_sa.sa_handler)) {
/* it there is no sa_sigaction function and the sa_handler is default, we can safely ignore this */
(SIG_DFL == previous_sa.sa_handler) && signo != SIGSEGV) {
/*
* If there is no sa_sigaction function and the sa_handler is default,
* it means the currently registered handler for this signal is the default one.
* For signal chaining, we need to store the default SIGSEGV handler so that the crash
* is properly propagated, while default handlers for other signals are ignored and
* are not considered.
*/
} else {
if (mono_do_signal_chaining)
save_old_signal_handler (signo, &previous_sa);
Expand Down
6 changes: 4 additions & 2 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3908,7 +3908,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);

if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
if (!mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
mono_chain_signal_to_default_sigsegv_handler ();
return;
}
}
Expand All @@ -3918,7 +3919,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
} else {
mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
if (!mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
mono_chain_signal_to_default_sigsegv_handler ();
return;
}
}
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 @@ -678,6 +678,7 @@ 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);
void mono_chain_signal_to_default_sigsegv_handler (void);

#if defined (HOST_WASM)

Expand Down
6 changes: 6 additions & 0 deletions src/mono/mono/mini/mini-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,12 @@ MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
return FALSE;
}

void
mono_chain_signal_to_default_sigsegv_handler (void)
{
g_error ("mono_chain_signal_to_default_sigsegv_handler not supported on WASM");
}

gboolean
mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info, void *sigctx)
{
Expand Down
6 changes: 6 additions & 0 deletions src/mono/mono/mini/mini-windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
return TRUE;
}

void
mono_chain_signal_to_default_sigsegv_handler (void)
{
g_error ("mono_chain_signal_to_default_sigsegv_handler not supported on Windows");
}

#if !HAVE_EXTERN_DEFINED_NATIVE_CRASH_HANDLER
#ifndef MONO_CROSS_COMPILE
void
Expand Down

0 comments on commit aa190d6

Please sign in to comment.