Repository: dotnet/runtime
File: src/coreclr/pal/src/exception/signal.cpp (C++)

Code before:
    }
    else if (IsSigDfl(action))
    {
        if (signalRestarts)
        {
            // Shutdown and create the core dump before we restore the signal to the default handler.
            PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

            PROCCreateCrashDumpIfEnabled(code, siginfo, context, true);

            // Restore the original and restart h/w exception.
            restore_signal(code, action);

            return;
        }
        else
        {
            // We can't invoke the original handler because returning from the
            // handler doesn't restart the exception.
            PROCAbort(code, siginfo, context);
        }
    }

    _ASSERTE(!IsSigDfl(action) && !IsSigIgn(action));

    PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

    PROCCreateCrashDumpIfEnabled(code, siginfo, context, true);

    if (IsSaSigInfo(action))
    {
        // Directly call the previous handler.
        _ASSERTE(action->sa_sigaction != NULL);
        action->sa_sigaction(code, siginfo, context);
    }
    else
    {
        // Directly call the previous handler.
        _ASSERTE(action->sa_handler != NULL);
        action->sa_handler(code);
    }
}

/*++
Function :
    sigill_handler

    handle SIGILL signal (EXCEPTION_ILLEGAL_INSTRUCTION, others?)

Parameters :
    POSIX signal handler parameter list ("man sigaction" for details)

Review comment (bug):
I do not think this works well when there are multiple runtimes loaded in the process that all want to handle segfaults. It can be multiple .NET runtimes (e.g. CoreCLR + NAOT, or multiple NAOT), or it can be .NET and some other runtime (e.g. Java runtime).

The expected behavior in these situations is that the given runtime will check whether the signal happened in the code that it cares about. If yes, it will handle the signal. If no, it will forward the signal to the next runtime, and so on.

With this change, I think we will shutdown our runtime instance and generate crashdump if there is segfault gracefully handled by some other runtime.

Code after:
    siginfo : signal siginfo
    context : signal context
    signalRestarts: BOOL state : TRUE if the process will be signalled again

    (no return value)
--*/
static void invoke_previous_action(struct sigaction* action, int code, siginfo_t *siginfo, void *context, bool signalRestarts = true)
{
    _ASSERTE(action != NULL);

    if (IsSigIgn(action))
    {
        if (signalRestarts)
        {
            // This signal mustn't be ignored because it will be restarted.
            PROCAbort(code, siginfo, context);
        }
        return;
    }
    else if (IsSigDfl(action))
    {
        if (signalRestarts)
        {
            // Shutdown and create the core dump before we restore the signal to the default handler.
            PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));

            PROCCreateCrashDumpIfEnabled(code, siginfo, context, true);

            // Restore the original and restart h/w exception.
            restore_signal(code, action);

            return;
        }
        else
        {
            // We can't invoke the original handler because returning from the
            // handler doesn't restart the exception.
            PROCAbort(code, siginfo, context);
        }
    }

    _ASSERTE(!IsSigDfl(action) && !IsSigIgn(action));

    if (g_crash_report_before_signal_chaining)
    {
        PROCNotifyProcessShutdown(IsRunningOnAlternateStack(context));
        PROCCreateCrashDumpIfEnabled(code, siginfo, context, true);
    }

    if (IsSaSigInfo(action))
    {