libc: support to execute signal on separate stack

With the commit LibC signals will be executed on a separate stack and
not anymore on the kernel or user stack.

Fixes #5305
This commit is contained in:
Alexander Boettcher 2024-07-18 17:11:41 +02:00 committed by Christian Helmuth
parent 992b412be2
commit 0c5df0036c

View File

@ -22,6 +22,7 @@
#include <signal.h>
/* libc-internal includes */
#include <internal/call_func.h>
#include <internal/types.h>
namespace Libc { struct Signal; }
@ -60,6 +61,52 @@ struct Libc::Signal : Noncopyable
pid_t const _local_pid;
void * _signal_stack { };
jmp_buf _signal_context { };
struct Signal_arguments
{
Signal & signal;
Pending & pending;
Signal_arguments(Signal &signal, Pending &pending)
: signal(signal), pending(pending) { }
};
static void _signal_entry(Signal_arguments &arg)
{
arg.signal._execute_signal_handler(arg.pending.n);
arg.signal._charged_signals[arg.pending.n].destruct();
_longjmp(arg.signal._signal_context, 1);
}
void _execute_on_signal_stack(Pending &pending)
{
if (!_signal_stack) {
auto myself = Thread::myself();
if (myself)
_signal_stack = { myself->alloc_secondary_stack("signal", 16 * 1024) };
}
if (!_signal_stack) {
error("signal stack allocation failed");
return;
}
/* save continuation of current stack */
if (!_setjmp(_signal_context)) {
Signal_arguments arg(*this, pending);
/* _setjmp() returned directly -> switch to signal stack */
call_func(_signal_stack, (void *)_signal_entry, (void *)&arg);
/* never reached */
}
/* _setjmp() returned after _longjmp() */
}
public:
Signal(pid_t local_pid) : _local_pid(local_pid) { }
@ -87,8 +134,7 @@ struct Libc::Signal : Noncopyable
_nesting_level++;
_pending_signals.for_each([&] (Pending &pending) {
_execute_signal_handler(pending.n);
_charged_signals[pending.n].destruct();
_execute_on_signal_stack(pending);
});
_nesting_level--;