diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-12-24 01:21:02 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-12-24 13:04:29 -0500 |
commit | 1227f793a3903adede083aba7cf3dcf0e4fba02d (patch) | |
tree | d675ea2472f2f5d77aba1bd34bb52e025d5f6372 /src | |
parent | 9a02b87dc137ee146bca5a0545201b4f27591405 (diff) | |
download | bfs-1227f793a3903adede083aba7cf3dcf0e4fba02d.tar.xz |
sighook: Preserve the exact siginfo_t in reraise() on Linux
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921
Diffstat (limited to 'src')
-rw-r--r-- | src/sighook.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/sighook.c b/src/sighook.c index e74bb78..6269614 100644 --- a/src/sighook.c +++ b/src/sighook.c @@ -32,6 +32,10 @@ #include <stdlib.h> #include <unistd.h> +#if __linux__ +# include <sys/syscall.h> +#endif + // NetBSD opens a file descriptor for each sem_init() #if defined(_POSIX_SEMAPHORES) && !__NetBSD__ # define BFS_POSIX_SEMAPHORES _POSIX_SEMAPHORES @@ -385,7 +389,9 @@ static bool is_fatal(int sig) { /** Reraise a fatal signal. */ _noreturn -static void reraise(int sig) { +static void reraise(siginfo_t *info) { + int sig = info->si_signo; + // Restore the default signal action if (signal(sig, SIG_DFL) == SIG_ERR) { goto fail; @@ -399,6 +405,13 @@ static void reraise(int sig) { goto fail; } +#if __linux__ + // On Linux, try to re-raise the exact siginfo_t (since 3.9, a process can + // signal itself with any siginfo_t) + pid_t tid = syscall(SYS_gettid); + syscall(SYS_rt_tgsigqueueinfo, getpid(), tid, sig, info); +#endif + raise(sig); fail: abort(); @@ -462,7 +475,7 @@ static void sigdispatch(int sig, siginfo_t *info, void *context) { return; } #endif - reraise(sig); + reraise(info); } // https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_04 @@ -482,7 +495,7 @@ static void sigdispatch(int sig, siginfo_t *info, void *context) { if (!(flags & SH_CONTINUE) && is_fatal(sig)) { list = siglist(0); run_hooks(list, sig, info); - reraise(sig); + reraise(info); } errno = error; |