From a54219532d26d3169c25986901976c4a7b742b69 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 16 Nov 2022 15:03:11 +0100 Subject: [PATCH 1/4] missing_syscall: Add rt_tgsigqueueinfo() --- meson.build | 4 ++++ src/basic/missing_syscall.h | 14 ++++++++++++++ 2 files changed, 18 insertions(+) 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[], From ee69f2b414ed3e92238231a166a36652405b857c Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 16 Nov 2022 15:05:24 +0100 Subject: [PATCH 2/4] sigbus: Make sure the signal is delivered to the same thread --- src/basic/sigbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c index d570b1df47..8d2c73baf8 100644 --- a/src/basic/sigbus.c +++ b/src/basic/sigbus.c @@ -102,7 +102,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); - rt_sigqueueinfo(getpid_cached(), SIGBUS, si); + rt_tgsigqueueinfo(getpid_cached(), gettid(), SIGBUS, si); return; } From a0f95434c0617b81f404d04c346aec5f288a29ce Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 16 Nov 2022 15:06:55 +0100 Subject: [PATCH 3/4] sigbus: Add fallback in case rt_tgsiqqueueinfo() fails --- src/basic/sigbus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c index 8d2c73baf8..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_tgsigqueueinfo(getpid_cached(), gettid(), SIGBUS, si); + if (rt_tgsigqueueinfo(getpid_cached(), gettid(), SIGBUS, si) < 0) + (void) raise(SIGBUS); return; } From 2af3e23fc085e6023b4906970f90757458fbb514 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sun, 5 Jun 2022 14:25:22 +0200 Subject: [PATCH 4/4] crash-handler: Make sure we propagate the original siginfo If we call raise(), we lose the information from the original signal. If we use rt_sigqueueinfo(), the original siginfo gets reused which is helpful when debugging crashes. --- src/core/crash-handler.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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);