From 86d14e0d0eedaaabcdf6081962fb5294051dd858 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 10 Jul 2023 21:54:04 +0200 Subject: [PATCH] kernel+libc: Add the SA_NODEFER and SA_RESETHAND flags for sigaction() --- apps/signal-test.cpp | 6 ++---- kernel/src/arch/x86_64/Thread.cpp | 12 ++++++++++-- libc/include/bits/signal.h | 4 ++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/signal-test.cpp b/apps/signal-test.cpp index 9062652c..b9f6df9a 100644 --- a/apps/signal-test.cpp +++ b/apps/signal-test.cpp @@ -5,16 +5,14 @@ void handler(int) { puts("I caught a segfault!"); - - struct sigaction sa; - sa.sa_handler = SIG_DFL; - sigaction(SIGSEGV, &sa, NULL); } int main() { struct sigaction sa; sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESETHAND; sigaction(SIGSEGV, &sa, NULL); #pragma GCC diagnostic ignored "-Wnonnull" diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index 2934e68a..c17cd7d4 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -120,8 +120,8 @@ bool Thread::deliver_signal(int signo, Registers* current_regs) if (push_mem_on_stack((u8*)&rsp, sizeof(u64)).has_error()) return false; if (push_mem_on_stack((u8*)&handler.__sa_sigreturn, sizeof(void*)).has_error()) return false; - // FIXME: Do not add the current signal to the signal mask if SA_NODEFER is set. - signal_mask = handler.sa_mask | (1 << (signo - 1)); + signal_mask = handler.sa_mask; + if ((handler.sa_flags & SA_NODEFER) == 0) signal_mask |= (1 << (signo - 1)); rsp = regs.rsp; @@ -132,6 +132,14 @@ bool Thread::deliver_signal(int signo, Registers* current_regs) memcpy(current_regs, ®s, sizeof(regs)); + if (handler.sa_flags & SA_RESETHAND) + { + handler.sa_handler = SIG_DFL; + handler.sa_mask = 0; + handler.sa_flags = 0; + signal_handlers[signo - 1] = handler; + } + return true; } diff --git a/libc/include/bits/signal.h b/libc/include/bits/signal.h index 423787e1..792f9840 100644 --- a/libc/include/bits/signal.h +++ b/libc/include/bits/signal.h @@ -22,6 +22,10 @@ struct sigaction #endif }; +// Constants for sigaction's sa_flags field. +#define SA_NODEFER (1 << 0) +#define SA_RESETHAND (1 << 1) + // Constants for the 'how' parameter in sigprocmask(). #define SIG_BLOCK 0 #define SIG_UNBLOCK 1