forked from git/git
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chain kill signals for cleanup functions
If a piece of code wanted to do some cleanup before exiting (e.g., cleaning up a lockfile or a tempfile), our usual strategy was to install a signal handler that did something like this: do_cleanup(); /* actual work */ signal(signo, SIG_DFL); /* restore previous behavior */ raise(signo); /* deliver signal, killing ourselves */ For a single handler, this works fine. However, if we want to clean up two _different_ things, we run into a problem. The most recently installed handler will run, but when it removes itself as a handler, it doesn't put back the first handler. This patch introduces sigchain, a tiny library for handling a stack of signal handlers. You sigchain_push each handler, and use sigchain_pop to restore whoever was before you in the stack. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
- Loading branch information
Showing
12 changed files
with
125 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include "sigchain.h" | ||
#include "cache.h" | ||
|
||
#define SIGCHAIN_MAX_SIGNALS 32 | ||
|
||
struct sigchain_signal { | ||
sigchain_fun *old; | ||
int n; | ||
int alloc; | ||
}; | ||
static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS]; | ||
|
||
static void check_signum(int sig) | ||
{ | ||
if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS) | ||
die("BUG: signal out of range: %d", sig); | ||
} | ||
|
||
int sigchain_push(int sig, sigchain_fun f) | ||
{ | ||
struct sigchain_signal *s = signals + sig; | ||
check_signum(sig); | ||
|
||
ALLOC_GROW(s->old, s->n + 1, s->alloc); | ||
s->old[s->n] = signal(sig, f); | ||
if (s->old[s->n] == SIG_ERR) | ||
return -1; | ||
s->n++; | ||
return 0; | ||
} | ||
|
||
int sigchain_pop(int sig) | ||
{ | ||
struct sigchain_signal *s = signals + sig; | ||
check_signum(sig); | ||
if (s->n < 1) | ||
return 0; | ||
|
||
if (signal(sig, s->old[s->n - 1]) == SIG_ERR) | ||
return -1; | ||
s->n--; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#ifndef SIGCHAIN_H | ||
#define SIGCHAIN_H | ||
|
||
typedef void (*sigchain_fun)(int); | ||
|
||
int sigchain_push(int sig, sigchain_fun f); | ||
int sigchain_pop(int sig); | ||
|
||
#endif /* SIGCHAIN_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/bin/sh | ||
|
||
test_description='signals work as we expect' | ||
. ./test-lib.sh | ||
|
||
cat >expect <<EOF | ||
three | ||
two | ||
one | ||
EOF | ||
|
||
test_expect_success 'sigchain works' ' | ||
test-sigchain >actual | ||
case "$?" in | ||
130) true ;; # POSIX w/ SIGINT=2 | ||
3) true ;; # Windows | ||
*) false ;; | ||
esac && | ||
test_cmp expect actual | ||
' | ||
|
||
test_done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include "sigchain.h" | ||
#include "cache.h" | ||
|
||
#define X(f) \ | ||
static void f(int sig) { \ | ||
puts(#f); \ | ||
fflush(stdout); \ | ||
sigchain_pop(sig); \ | ||
raise(sig); \ | ||
} | ||
X(one) | ||
X(two) | ||
X(three) | ||
#undef X | ||
|
||
int main(int argc, char **argv) { | ||
sigchain_push(SIGINT, one); | ||
sigchain_push(SIGINT, two); | ||
sigchain_push(SIGINT, three); | ||
raise(SIGINT); | ||
return 0; | ||
} |