diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2025-01-18 12:59:33 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2025-01-18 12:59:33 -0500 |
commit | 62928ddf80fea0291cf40d95877bb5b6f9d110c9 (patch) | |
tree | 1db1689d2e145fa5957717cb62133d4a24b0171e /src/sighook.c | |
parent | 41f3283ec38e0cc27e350569bef3651e16447ce0 (diff) | |
download | bfs-62928ddf80fea0291cf40d95877bb5b6f9d110c9.tar.xz |
sighook: New sigreset() function to reset all handlers
Diffstat (limited to 'src/sighook.c')
-rw-r--r-- | src/sighook.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/sighook.c b/src/sighook.c index a1fc30d..820044c 100644 --- a/src/sighook.c +++ b/src/sighook.c @@ -525,6 +525,18 @@ static void sigdispatch(int sig, siginfo_t *info, void *context) { errno = error; } +/** A saved signal handler, for sigreset() to restore. */ +struct sigsave { + struct rcu_node node; + int sig; + struct sigaction action; +}; + +/** The list of saved signal handlers. */ +static struct rcu_list saved; +/** `saved` initialization status (since rcu_list_init() isn't atomic). */ +static atomic bool initialized = false; + /** Make sure our signal handler is installed for a given signal. */ static int siginit(int sig) { #ifdef SA_RESTART @@ -539,9 +551,8 @@ static int siginit(int sig) { }; static sigset_t signals; - static bool initialized = false; - if (!initialized) { + if (!load(&initialized, relaxed)) { if (sigemptyset(&signals) != 0 || sigemptyset(&action.sa_mask) != 0) { return -1; @@ -551,7 +562,8 @@ static int siginit(int sig) { rcu_list_init(&sighooks[i]); } - initialized = true; + rcu_list_init(&saved); + store(&initialized, true, release); } int installed = sigismember(&signals, sig); @@ -561,6 +573,18 @@ static int siginit(int sig) { return 0; } + struct sigsave *save = ALLOC(struct sigsave); + if (!save) { + return -1; + } + + save->sig = sig; + if (sigaction(sig, NULL, &save->action) != 0) { + free(save); + return -1; + } + rcu_list_append(&saved, &save->node); + if (sigaction(sig, &action, NULL) != 0) { return -1; } @@ -639,3 +663,13 @@ void sigunhook(struct sighook *hook) { free(hook); } + +int sigreset(void) { + for_rcu (struct sigsave, save, &saved) { + if (sigaction(save->sig, &save->action, NULL) != 0) { + return -1; + } + } + + return 0; +} |