From: Lennart Poettering Date: Wed, 16 Nov 2022 17:54:29 +0000 (+0100) Subject: signal-util: add common implementation for propagating a signal X-Git-Tag: v253-rc1~505 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=128a11ea9905ee3a9d2c6baeaf65618a21272f97;p=thirdparty%2Fsystemd.git signal-util: add common implementation for propagating a signal i.e. let's add a common logic to be called from a signal handler to raise the passed signal again. Follow-up for: #25399 --- diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c index 0dca7be479f..7e5a493f6b0 100644 --- a/src/basic/sigbus.c +++ b/src/basic/sigbus.c @@ -10,6 +10,7 @@ #include "missing_syscall.h" #include "process-util.h" #include "sigbus.h" +#include "signal-util.h" #define SIGBUS_QUEUE_MAX 64 @@ -102,8 +103,7 @@ static void sigbus_handler(int sn, siginfo_t *si, void *data) { if (si->si_code != BUS_ADRERR || !si->si_addr) { assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0); - if (rt_tgsigqueueinfo(getpid_cached(), gettid(), SIGBUS, si) < 0) - (void) raise(SIGBUS); + propagate_signal(sn, si); return; } diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c index b61c18b2dec..7875ca69bb7 100644 --- a/src/basic/signal-util.c +++ b/src/basic/signal-util.c @@ -5,6 +5,7 @@ #include "errno-util.h" #include "macro.h" +#include "missing_syscall.h" #include "parse-util.h" #include "signal-util.h" #include "stdio-util.h" @@ -282,3 +283,20 @@ int pop_pending_signal_internal(int sig, ...) { return r; /* Returns the signal popped */ } + +void propagate_signal(int sig, siginfo_t *siginfo) { + pid_t p; + + /* To be called from a signal handler. Will raise the same signal again, in our process + in our threads. + * + * Note that we use raw_getpid() instead of getpid_cached(). We might have forked with raw_clone() + * earlier (see PID 1), and hence let's go to the raw syscall here. In particular as this is not + * performance sensitive code. + * + * Note that we use kill() rather than raise() as fallback, for similar reasons. */ + + p = raw_getpid(); + + if (rt_tgsigqueueinfo(p, gettid(), sig, siginfo) < 0) + assert_se(kill(p, sig) >= 0); +} diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h index 36372c19bd8..ad2ba841c6e 100644 --- a/src/basic/signal-util.h +++ b/src/basic/signal-util.h @@ -65,3 +65,5 @@ int signal_is_blocked(int sig); int pop_pending_signal_internal(int sig, ...); #define pop_pending_signal(...) pop_pending_signal_internal(__VA_ARGS__, -1) + +void propagate_signal(int sig, siginfo_t *siginfo); diff --git a/src/core/crash-handler.c b/src/core/crash-handler.c index fced3ccf5aa..6983f2e2b7f 100644 --- a/src/core/crash-handler.c +++ b/src/core/crash-handler.c @@ -47,11 +47,10 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) { * memory allocation is not async-signal-safe anyway — see signal-safety(7) for details —, and thus * is not permissible in signal handlers.) */ - if (getpid_cached() != 1) { + if (getpid_cached() != 1) /* Pass this on immediately, if this is not PID 1 */ - if (rt_tgsigqueueinfo(getpid_cached(), gettid(), sig, siginfo) < 0) - (void) raise(sig); - } else if (!arg_dump_core) + propagate_signal(sig, siginfo); + else if (!arg_dump_core) log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig)); else { sa = (struct sigaction) { @@ -80,10 +79,7 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) { (void) chdir("/"); /* Raise the signal again */ - pid = raw_getpid(); - if (rt_tgsigqueueinfo(pid, gettid(), sig, siginfo) < 0) - (void) kill(pid, sig); /* raise() would kill the parent */ - + propagate_signal(sig, siginfo); assert_not_reached(); _exit(EXIT_EXCEPTION); } else {