2626//
2727
2828#include "SentryCrashMonitor_Signal.h"
29+ #include "SentryCrashCPU.h"
2930#include "SentryCrashID.h"
3031#include "SentryCrashMachineContext.h"
3132#include "SentryCrashMonitorContext.h"
33+ #include "SentryCrashMonitor_MachException.h"
3234#include "SentryCrashSignalInfo.h"
3335#include "SentryCrashStackCursor_MachineContext.h"
3436#include "SentryInternalCDefines.h"
4951
5052static volatile bool g_isEnabled = false;
5153static bool g_isSigtermReportingEnabled = false;
54+ static bool g_isManagedRuntime = false;
5255
5356static SentryCrash_MonitorContext g_monitorContext ;
5457static SentryCrashStackCursor g_stackCursor ;
@@ -67,6 +70,29 @@ static char g_eventID[37];
6770# pragma mark - Callbacks -
6871// ============================================================================
6972
73+ /**
74+ *
75+ */
76+ static void
77+ invokePreviousSignalHandlers (int sigNum , siginfo_t * signalInfo , void * userContext )
78+ {
79+ const int * fatalSignals = sentrycrashsignal_fatalSignals ();
80+ int fatalSignalsCount = sentrycrashsignal_numFatalSignals ();
81+
82+ for (int i = 0 ; i < fatalSignalsCount ; ++ i ) {
83+ if (fatalSignals [i ] == sigNum ) {
84+ struct sigaction * handler = & g_previousSignalHandlers [i ];
85+ if (handler -> sa_flags & SA_SIGINFO ) {
86+ handler -> sa_sigaction (sigNum , signalInfo , userContext );
87+ } else if (handler -> sa_handler != SIG_DFL && handler -> sa_handler != SIG_IGN ) {
88+ // This handler can only handle to signal number (ANSI C)
89+ void (* func )(int ) = handler -> sa_handler ;
90+ func (sigNum );
91+ }
92+ }
93+ }
94+ }
95+
7096/** Our custom signal handler.
7197 * Restore the default signal handlers, record the signal information, and
7298 * write a crash report.
@@ -83,6 +109,29 @@ static void
83109handleSignal (int sigNum , siginfo_t * signalInfo , void * userContext )
84110{
85111 SENTRY_ASYNC_SAFE_LOG_DEBUG ("Trapped signal %d" , sigNum );
112+
113+ // Let managed Mono/CoreCLR runtime handle the signal first,
114+ // as they may convert it into a managed exception.
115+ if (g_isManagedRuntime ) {
116+ SENTRY_ASYNC_SAFE_LOG_DEBUG (
117+ "Detected managed Mono/CoreCLR runtime. Passing signal to previous handlers." );
118+
119+ uintptr_t sp = sentrycrashcpu_stackPointerFromUserContext (userContext );
120+ uintptr_t ip = sentrycrashcpu_instructionAddressFromUserContext (userContext );
121+
122+ invokePreviousSignalHandlers (sigNum , signalInfo , userContext );
123+
124+ // If the stack or instruction pointer changed, the managed runtime
125+ // converted the signal into a managed exception and changed the context.
126+ // https://github.com/dotnet/runtime/blob/6d96e28597e7da0d790d495ba834cc4908e442cd/src/mono/mono/mini/exceptions-arm64.c#L538
127+ if (sp != sentrycrashcpu_stackPointerFromUserContext (userContext )
128+ || ip != sentrycrashcpu_instructionAddressFromUserContext (userContext )) {
129+ SENTRY_ASYNC_SAFE_LOG_DEBUG (
130+ "Signal converted to a managed exception. Aborting signal handling." );
131+ return ;
132+ }
133+ }
134+
86135 if (g_isEnabled ) {
87136 thread_act_array_t threads = NULL ;
88137 mach_msg_type_number_t numThreads = 0 ;
@@ -110,9 +159,13 @@ handleSignal(int sigNum, siginfo_t *signalInfo, void *userContext)
110159 sentrycrashmc_resumeEnvironment (threads , numThreads );
111160 }
112161
113- SENTRY_ASYNC_SAFE_LOG_DEBUG ("Re-raising signal for regular handlers to catch." );
114- // This is technically not allowed, but it works in OSX and iOS.
115- raise (sigNum );
162+ // Re-raise the signal to invoke the previous handlers unless already called
163+ // above for managed runtimes.
164+ if (!g_isManagedRuntime ) {
165+ SENTRY_ASYNC_SAFE_LOG_DEBUG ("Re-raising signal for regular handlers to catch." );
166+ // This is technically not allowed, but it works in OSX and iOS.
167+ raise (sigNum );
168+ }
116169}
117170
118171// ============================================================================
@@ -124,6 +177,8 @@ installSignalHandler(void)
124177{
125178 SENTRY_ASYNC_SAFE_LOG_DEBUG ("Installing signal handler." );
126179
180+ g_isManagedRuntime = sentrycrashcm_isManagedRuntime ();
181+
127182# if SENTRY_HAS_SIGNAL_STACK
128183
129184 if (g_signalStack .ss_size == 0 ) {
0 commit comments