diff --git a/meson.build b/meson.build index 55ed968798..8a4552d5bb 100644 --- a/meson.build +++ b/meson.build @@ -599,6 +599,10 @@ foreach ident : [ #include #include #include '''], + ['rt_tgsigqueueinfo', '''#include + #include + #include + #include '''], ['mallinfo', '''#include '''], ['mallinfo2', '''#include '''], ['execveat', '''#include '''], diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index d54e59fdf9..6ad89da541 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -363,6 +363,20 @@ static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) /* ======================================================================= */ +#if !HAVE_RT_TGSIGQUEUEINFO +static inline int missing_rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *info) { +# if defined __NR_rt_tgsigqueueinfo && __NR_rt_tgsigqueueinfo >= 0 + return syscall(__NR_rt_tgsigqueueinfo, tgid, tid, sig, info); +# else +# error "__NR_rt_tgsigqueueinfo not defined" +# endif +} + +# define rt_tgsigqueueinfo missing_rt_tgsigqueueinfo +#endif + +/* ======================================================================= */ + #if !HAVE_EXECVEAT static inline int missing_execveat(int dirfd, const char *pathname, char *const argv[], char *const envp[], diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c index d570b1df47..0dca7be479 100644 --- a/src/basic/sigbus.c +++ b/src/basic/sigbus.c @@ -102,7 +102,8 @@ 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); - rt_sigqueueinfo(getpid_cached(), SIGBUS, si); + if (rt_tgsigqueueinfo(getpid_cached(), gettid(), SIGBUS, si) < 0) + (void) raise(SIGBUS); return; } diff --git a/src/core/crash-handler.c b/src/core/crash-handler.c index 561b7fc19c..fced3ccf5a 100644 --- a/src/core/crash-handler.c +++ b/src/core/crash-handler.c @@ -47,10 +47,11 @@ _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 */ - (void) raise(sig); - else if (!arg_dump_core) + if (rt_tgsigqueueinfo(getpid_cached(), gettid(), sig, siginfo) < 0) + (void) raise(sig); + } else if (!arg_dump_core) log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig)); else { sa = (struct sigaction) { @@ -80,7 +81,8 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) { /* Raise the signal again */ pid = raw_getpid(); - (void) kill(pid, sig); /* raise() would kill the parent */ + if (rt_tgsigqueueinfo(pid, gettid(), sig, siginfo) < 0) + (void) kill(pid, sig); /* raise() would kill the parent */ assert_not_reached(); _exit(EXIT_EXCEPTION);