mirror of
https://github.com/systemd/systemd.git
synced 2026-08-03 14:40:31 +00:00
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
This commit is contained in:
committed by
Yu Watanabe
parent
58dad4d5e5
commit
128a11ea99
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user