]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
signal-util: add common implementation for propagating a signal
authorLennart Poettering <lennart@poettering.net>
Wed, 16 Nov 2022 17:54:29 +0000 (18:54 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 17 Nov 2022 13:38:14 +0000 (22:38 +0900)
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

src/basic/sigbus.c
src/basic/signal-util.c
src/basic/signal-util.h
src/core/crash-handler.c

index 0dca7be479f305385a06eeeaaa13a37415683cb7..7e5a493f6b03b57e75c6be10368e588e39f75222 100644 (file)
@@ -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;
         }
 
index b61c18b2dec14970c78078cb98d90d401b515d41..7875ca69bb7d2444764dbebbbfff647e2f6a16e1 100644 (file)
@@ -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);
+}
index 36372c19bd8a989d910764b3330c2509d97b5558..ad2ba841c6eccfffeb38ef2e50a650dc0c00648e 100644 (file)
@@ -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);
index fced3ccf5aa6d87e76806df4e2aa1415b27f705d..6983f2e2b7f83a84b7a73defef1e88e1cdc9b130 100644 (file)
@@ -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 {