The default handlers for SIGTRAP, SIGSYS on macOS and Linux crash the process, so we now have Mono report this.
This change also changes the presentation of the signal name on the stacktrace report dumped on error (from e.g. "SIGSEGV" to "segv").
Co-authored-by: Alexis Christoforides <alexis@thenull.net>
fi
dnl ********************************
+ dnl *** Checks for sys_signame ***
+ dnl ********************************
+ AC_MSG_CHECKING(for sys_signame)
+ AC_TRY_LINK([
+ #include <signal.h>
+ ], [
+ const char *signame = sys_signame[0];
+ ], [
+ # Yes, we have it...
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SYSSIGNAME, 1, [Have sys_signame])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+
+
+ dnl ********************************
dnl *** Checks for semaphore lib ***
dnl ********************************
# 'Real Time' functions on Solaris
#include "icall-decl.h"
#include "mono/utils/mono-threads-coop.h"
#include "mono/metadata/icall-signatures.h"
+#include "mono/utils/mono-signal-handler.h"
//#define MONO_DEBUG_ICALLARRAY
hashes.offset_rich_hash = unportable_hash;
// Tells mono that we want to send the HANG EXC_TYPE.
- const char *signal = "SIGTERM";
+ const char *signal = mono_get_signame (SIGTERM);
gboolean success = mono_merp_invoke (crashed_pid, signal, payload, &hashes);
if (!success) {
#endif
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", NULL, NULL);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), NULL, NULL);
return EXCEPTION_CONTINUE_SEARCH;
}
if (!ji || (!stack_ovf && !nullref)) {
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", ctx, NULL);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), ctx, NULL);
// if couldn't dump or if mono_handle_native_crash returns, abort
abort ();
}
}
if (!ji)
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", (MonoContext*)sigctx, siginfo);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), (MonoContext*)sigctx, siginfo);
/* setup a call frame on the real stack so that control is returned there
* and exception handling can continue.
* The frame looks like:
}
#endif
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", NULL, NULL);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), NULL, NULL);
return EXCEPTION_CONTINUE_SEARCH;
}
MonoContext mctx;
mono_sigctx_to_monoctx (sigctx, &mctx);
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", &mctx, siginfo);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, siginfo);
else
abort ();
}
return;
mono_sigctx_to_monoctx (ctx, &mctx);
if (mono_dump_start ())
- mono_handle_native_crash ("SIGABRT", &mctx, info);
+ mono_handle_native_crash (mono_get_signame (info->si_signo), &mctx, info);
else
abort ();
}
MONO_SIG_HANDLER_FUNC (static, sigterm_signal_handler)
{
#ifndef DISABLE_CRASH_REPORTING
+ MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
MONO_SIG_HANDLER_GET_CONTEXT;
// Note: this is only run from the non-controlling thread
// running. Returns FALSE on unrecoverable error.
if (mono_dump_start ()) {
// Process was killed from outside since crash reporting wasn't running yet.
- mono_handle_native_crash ("SIGTERM", &mctx, NULL);
+ mono_handle_native_crash (mono_get_signame (info->si_signo), &mctx, NULL);
} else {
// Crash reporting already running and we got a second SIGTERM from as part of thread-summarizing
if (!mono_threads_summarize_execute (&mctx, &output, &hashes, FALSE, NULL, 0))
sigset_t signal_set;
sigemptyset (&signal_set);
+ mono_load_signames ();
if (mini_debug_options.handle_sigint) {
add_signal_handler (SIGINT, mono_sigint_signal_handler, SA_RESTART);
sigaddset (&signal_set, SIGINT);
sigaddset (&signal_set, SIGFPE);
add_signal_handler (SIGQUIT, sigquit_signal_handler, SA_RESTART);
sigaddset (&signal_set, SIGQUIT);
- add_signal_handler (SIGILL, mono_sigill_signal_handler, 0);
+ add_signal_handler (SIGILL, mono_crashing_signal_handler, 0);
sigaddset (&signal_set, SIGILL);
add_signal_handler (SIGBUS, mono_sigsegv_signal_handler, 0);
sigaddset (&signal_set, SIGBUS);
add_signal_handler (SIGUSR2, sigusr2_signal_handler, SA_RESTART);
sigaddset (&signal_set, SIGUSR2);
}
+ add_signal_handler (SIGTRAP, mono_crashing_signal_handler, 0);
+ sigaddset (&signal_set, SIGTRAP);
+ add_signal_handler (SIGSYS, mono_crashing_signal_handler, 0);
+ sigaddset (&signal_set, SIGSYS);
/* it seems to have become a common bug for some programs that run as parents
* of many processes to block signal delivery for real time signals.
mono_sigctx_to_monoctx (ctx, &mctx);
if (mono_dump_start ())
- mono_handle_native_crash ("SIGFPE", &mctx, info);
+ mono_handle_native_crash (mono_get_signame (SIGFPE), &mctx, info);
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
goto exit;
MONO_EXIT_GC_UNSAFE_UNBALANCED;
}
-MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_crashing_signal_handler)
{
MonoContext mctx;
MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
mono_sigctx_to_monoctx (ctx, &mctx);
if (mono_dump_start ())
- mono_handle_native_crash ("SIGILL", &mctx, info);
+#if defined(HAVE_SIG_INFO) && !defined(HOST_WIN32) // info is a siginfo_t
+ mono_handle_native_crash (mono_get_signame (info->si_signo), &mctx, info);
+#else
+ mono_handle_native_crash (mono_get_signame (SIGTERM), &mctx, info);
+#endif
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
}
-
}
#if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
mono_aot_handle_pagefault (info->si_addr);
return;
}
+ int signo = info->si_signo;
+#else
+ int signo = SIGSEGV;
#endif
/* The thread might no be registered with the runtime */
if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
if (mono_dump_start())
- mono_handle_native_crash ("SIGSEGV", &mctx, info);
+ mono_handle_native_crash (mono_get_signame (signo), &mctx, info);
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
} else {
// FIXME: This shouldn't run on the altstack
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", &mctx, info);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, info);
}
#endif
}
return;
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
+ 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);
mono_arch_handle_exception (ctx, NULL);
} else {
if (mono_dump_start ())
- mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
+ mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
}
#endif
}
#endif
void MONO_SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) ;
-void MONO_SIG_HANDLER_SIGNATURE (mono_sigill_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) ;
gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal);
#ifndef MONO_CROSS_COMPILE
win32_seh_init();
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
- win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+ win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
if (mini_debug_options.handle_sigint)
win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
bsearch.h \
bsearch.c \
mono-signal-handler.h \
+ mono-signal-handler.c \
mono-conc-hashtable.h \
mono-conc-hashtable.c \
json.h \
#include <mono/utils/json.h>
#include <mono/utils/mono-state.h>
#include <utils/mono-threads-debug.h>
+#include <utils/mono-signal-handler.h>
static const char *
kernel_version_string (void)
static MERPExcType
parse_exception_type (const char *signal)
{
- if (!strcmp (signal, "SIGSEGV"))
+ if (!strcmp (signal, mono_get_signame (SIGSEGV)))
return MERP_EXC_SIGSEGV;
- if (!strcmp (signal, "SIGFPE"))
+ if (!strcmp (signal, mono_get_signame (SIGFPE)))
return MERP_EXC_SIGFPE;
- if (!strcmp (signal, "SIGILL"))
+ if (!strcmp (signal, mono_get_signame (SIGILL)))
return MERP_EXC_SIGILL;
- if (!strcmp (signal, "SIGABRT"))
+ if (!strcmp (signal, mono_get_signame (SIGABRT)))
return MERP_EXC_SIGABRT;
+ if (!strcmp (signal, mono_get_signame (SIGTRAP)))
+ return MERP_EXC_SIGTRAP;
+
+ if (!strcmp (signal, mono_get_signame (SIGSYS)))
+ return MERP_EXC_SIGSYS;
+
// Force quit == hang?
// We need a default for this
- if (!strcmp (signal, "SIGTERM"))
+ if (!strcmp (signal, mono_get_signame (SIGTERM)))
return MERP_EXC_HANG;
// FIXME: There are no other such signal
--- /dev/null
+#include "config.h"
+#include <signal.h>
+#include <string.h>
+#include "mono/utils/mono-signal-handler.h"
+
+struct mono_sigpair
+{
+ int signo;
+ const char* signame;
+};
+
+#if !defined (HAVE_SYSSIGNAME)
+static struct mono_sigpair mono_signames[] =
+{
+ {SIGABRT, "SIGABRT"},
+#if defined (SIGKILL)
+ {SIGKILL, "SIGKILL"},
+#endif
+#if defined (SIGTRAP)
+ {SIGTRAP, "SIGTRAP"},
+#endif
+#if defined (SIGSYS)
+ {SIGSYS, "SIGSYS"},
+#endif
+ {SIGSEGV, "SIGSEGV"},
+#if defined (SIGQUIT)
+ {SIGQUIT, "SIGQUIT"},
+#endif
+ {SIGFPE, "SIGFPE"},
+ {SIGILL, "SIGILL"},
+#if defined (SIGBUS)
+ {SIGBUS, "SIGBUS"} // How come this is seems not available on Android, but is used unconditionally in mini-posix.c:mono_runtime_posix_install_handlers ?
+#endif
+};
+#endif
+
+static struct mono_sigpair *sigpair_buf;
+static int sigpair_buflen;
+
+void
+mono_load_signames ()
+{
+ if (sigpair_buf)
+ return;
+#if defined (HAVE_SYSSIGNAME)
+ sigpair_buflen = sizeof (sys_signame) / sizeof (sys_signame [0]);
+ sigpair_buf = (struct mono_sigpair *) g_malloc (sigpair_buflen * sizeof (struct mono_sigpair));
+ struct mono_sigpair *cur = sigpair_buf;
+ for (int i = 0; i < sigpair_buflen; ++i)
+ {
+ cur->signo = i;
+ cur->signame = sys_signame [i];
+ cur++;
+ }
+
+#else
+ sigpair_buflen = sizeof (mono_signames) / sizeof (mono_signames [0]);
+ sigpair_buf = mono_signames;
+#endif
+
+}
+
+const char *
+mono_get_signame (int signo)
+{
+ const char *result = "UNKNOWN";
+ struct mono_sigpair *cur = sigpair_buf;
+ for (int i = 0; i < sigpair_buflen; ++i)
+ {
+ if (cur->signo == signo)
+ {
+ result = cur->signame;
+ break;
+ }
+ cur++;
+ }
+ return result;
+}
#define __MONO_SIGNAL_HANDLER_H__
#include "config.h"
+#include <glib.h>
/*
* When a signal is delivered to a thread on a Krait Android device
*/
#ifdef HOST_WIN32
+#include <windows.h>
#define MONO_SIG_HANDLER_INFO_TYPE MonoWindowsSigHandlerInfo
typedef struct {
/* Set to FALSE to indicate chained signal handler needs run.
#define MONO_SIG_HANDLER_GET_INFO() (_info)
#define MONO_SIG_HANDLER_GET_CONTEXT void *ctx = context;
+void mono_load_signames (void);
+const char * mono_get_signame (int signo);
+
#endif // __MONO_SIGNAL_HANDLER_H__
<ClInclude Include="$(MonoSourceLocation)\mono\utils\bsearch.h" />
<ClCompile Include="$(MonoSourceLocation)\mono\utils\bsearch.c" />
<ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.h" />
+ <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.c" />
<ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-conc-hashtable.h" />
<ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-conc-hashtable.c" />
<ClInclude Include="$(MonoSourceLocation)\mono\utils\json.h" />
<ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.h">
<Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
</ClInclude>
+ <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.c">
+ <Filter>Source Files$(MonoUtilsFilterSubFolder)\common</Filter>
+ </ClCompile>
<ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-conc-hashtable.h">
<Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
</ClInclude>