Skip to content

Commit fde353a

Browse files
janvorlimikelle-rogers
authored andcommitted
Fix stack overflow handling with SuperPMI (dotnet#106495)
* Fix stack overflow handling with SuperPMI When SuperPMI shared library is loaded last, its SIGSEGV handler is the first one that's executed. But since there is no coreclr runtime handler installed for it, it returns from the SwitchStackAndExecuteHandler in case of SIGSEGV. The remaining code in the SIGSEGV handler was not expecting that and thought that there was no stack overflow and attempted to run the hardware exception handler on the original stack of the thread, which obviously crashed since the original stack overflowed. The fix is to make sure that we only call the previously registered signal handler in this case. Close dotnet#84911 * PR feedback
1 parent f08d277 commit fde353a

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

src/coreclr/pal/src/exception/signal.cpp

+22-17
Original file line numberDiff line numberDiff line change
@@ -641,34 +641,39 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
641641
{
642642
PROCAbort(SIGSEGV, siginfo);
643643
}
644+
645+
// The current executable (shared library) doesn't have hardware exception handler installed or opted to not to
646+
// handle it. So this handler will invoke the previously installed handler at the end of this function.
644647
}
645648
else
646649
{
647650
(void)!write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1);
648651
PROCAbort(SIGSEGV, siginfo);
649652
}
650653
}
651-
652-
// Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common
653-
// hardware signal handler on the original stack.
654-
655-
if (GetCurrentPalThread() && IsRunningOnAlternateStack(context))
654+
else
656655
{
657-
if (SwitchStackAndExecuteHandler(code, siginfo, context, 0 /* sp */)) // sp == 0 indicates execution on the original stack
656+
// Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common
657+
// hardware signal handler on the original stack.
658+
659+
if (GetCurrentPalThread() && IsRunningOnAlternateStack(context))
658660
{
659-
return;
661+
if (SwitchStackAndExecuteHandler(code, siginfo, context, 0 /* sp */)) // sp == 0 indicates execution on the original stack
662+
{
663+
return;
664+
}
660665
}
661-
}
662-
else
663-
{
664-
// The code flow gets here when the signal handler is not running on an alternate stack or when it wasn't created
665-
// by coreclr. In both cases, we execute the common_signal_handler directly.
666-
// If thread isn't created by coreclr and has alternate signal stack GetCurrentPalThread() will return NULL too.
667-
// But since in this case we don't handle hardware exceptions (IsSafeToHandleHardwareException returns false)
668-
// we can call common_signal_handler on the alternate stack.
669-
if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr))
666+
else
670667
{
671-
return;
668+
// The code flow gets here when the signal handler is not running on an alternate stack or when it wasn't created
669+
// by coreclr. In both cases, we execute the common_signal_handler directly.
670+
// If thread isn't created by coreclr and has alternate signal stack GetCurrentPalThread() will return NULL too.
671+
// But since in this case we don't handle hardware exceptions (IsSafeToHandleHardwareException returns false)
672+
// we can call common_signal_handler on the alternate stack.
673+
if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr))
674+
{
675+
return;
676+
}
672677
}
673678
}
674679
}

0 commit comments

Comments
 (0)