From 4a16d072723b48699ea162da24eff05eba298834 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 22 Jan 2009 01:02:35 -0500 Subject: 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 Signed-off-by: Junio C Hamano --- http-push.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'http-push.c') diff --git a/http-push.c b/http-push.c index a4b7d08663..dec395deed 100644 --- a/http-push.c +++ b/http-push.c @@ -10,6 +10,7 @@ #include "exec_cmd.h" #include "remote.h" #include "list-objects.h" +#include "sigchain.h" #include @@ -1363,7 +1364,7 @@ static void remove_locks(void) static void remove_locks_on_signal(int signo) { remove_locks(); - signal(signo, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -2261,10 +2262,10 @@ int main(int argc, char **argv) goto cleanup; } - signal(SIGINT, remove_locks_on_signal); - signal(SIGHUP, remove_locks_on_signal); - signal(SIGQUIT, remove_locks_on_signal); - signal(SIGTERM, remove_locks_on_signal); + sigchain_push(SIGINT, remove_locks_on_signal); + sigchain_push(SIGHUP, remove_locks_on_signal); + sigchain_push(SIGQUIT, remove_locks_on_signal); + sigchain_push(SIGTERM, remove_locks_on_signal); /* Check whether the remote has server info files */ remote->can_update_info_refs = 0; -- cgit v1.3 From 57b235a4bc8884a57c6f863605a54b7bfceb0997 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 22 Jan 2009 01:03:08 -0500 Subject: refactor signal handling for cleanup functions The current code is very inconsistent about which signals are caught for doing cleanup of temporary files and lock files. Some callsites checked only SIGINT, while others checked a variety of death-dealing signals. This patch factors out those signals to a single function, and then calls it everywhere. For some sites, that means this is a simple clean up. For others, it is an improvement in that they will now properly clean themselves up after a larger variety of signals. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-clone.c | 2 +- builtin-fetch--tool.c | 2 +- builtin-fetch.c | 2 +- diff.c | 2 +- http-push.c | 5 +---- lockfile.c | 6 +----- sigchain.c | 9 +++++++++ sigchain.h | 2 ++ 8 files changed, 17 insertions(+), 13 deletions(-) (limited to 'http-push.c') diff --git a/builtin-clone.c b/builtin-clone.c index 18b9392334..44c80734b7 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -439,7 +439,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } junk_git_dir = git_dir; atexit(remove_junk); - sigchain_push(SIGINT, remove_junk_on_signal); + sigchain_push_common(remove_junk_on_signal); setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1); diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index b1d7f8fb32..29356d25db 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -246,7 +246,7 @@ static int fetch_native_store(FILE *fp, char buffer[1024]; int err = 0; - sigchain_push(SIGINT, remove_keep_on_signal); + sigchain_push_common(remove_keep_on_signal); atexit(remove_keep); while (fgets(buffer, sizeof(buffer), stdin)) { diff --git a/builtin-fetch.c b/builtin-fetch.c index 8c86974cbe..1e4a3d9c51 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -673,7 +673,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) ref_nr = j; } - sigchain_push(SIGINT, unlock_pack_on_signal); + sigchain_push_common(unlock_pack_on_signal); atexit(unlock_pack); exit_code = do_fetch(transport, parse_fetch_refspec(ref_nr, refs), ref_nr); diff --git a/diff.c b/diff.c index 9c9977d892..8ce898a6b0 100644 --- a/diff.c +++ b/diff.c @@ -1903,7 +1903,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (!remove_tempfile_installed) { atexit(remove_tempfile); - sigchain_push(SIGINT, remove_tempfile_on_signal); + sigchain_push_common(remove_tempfile_on_signal); remove_tempfile_installed = 1; } diff --git a/http-push.c b/http-push.c index dec395deed..7d5c23edc4 100644 --- a/http-push.c +++ b/http-push.c @@ -2262,10 +2262,7 @@ int main(int argc, char **argv) goto cleanup; } - sigchain_push(SIGINT, remove_locks_on_signal); - sigchain_push(SIGHUP, remove_locks_on_signal); - sigchain_push(SIGQUIT, remove_locks_on_signal); - sigchain_push(SIGTERM, remove_locks_on_signal); + sigchain_push_common(remove_locks_on_signal); /* Check whether the remote has server info files */ remote->can_update_info_refs = 0; diff --git a/lockfile.c b/lockfile.c index 3cd57dc385..021c3375c1 100644 --- a/lockfile.c +++ b/lockfile.c @@ -137,11 +137,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags) lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666); if (0 <= lk->fd) { if (!lock_file_list) { - sigchain_push(SIGINT, remove_lock_file_on_signal); - sigchain_push(SIGHUP, remove_lock_file_on_signal); - sigchain_push(SIGTERM, remove_lock_file_on_signal); - sigchain_push(SIGQUIT, remove_lock_file_on_signal); - sigchain_push(SIGPIPE, remove_lock_file_on_signal); + sigchain_push_common(remove_lock_file_on_signal); atexit(remove_lock_file); } lk->owner = getpid(); diff --git a/sigchain.c b/sigchain.c index a18d505e56..1118b99e57 100644 --- a/sigchain.c +++ b/sigchain.c @@ -41,3 +41,12 @@ int sigchain_pop(int sig) s->n--; return 0; } + +void sigchain_push_common(sigchain_fun f) +{ + sigchain_push(SIGINT, f); + sigchain_push(SIGHUP, f); + sigchain_push(SIGTERM, f); + sigchain_push(SIGQUIT, f); + sigchain_push(SIGPIPE, f); +} diff --git a/sigchain.h b/sigchain.h index 254ebb0fa6..618083bce0 100644 --- a/sigchain.h +++ b/sigchain.h @@ -6,4 +6,6 @@ typedef void (*sigchain_fun)(int); int sigchain_push(int sig, sigchain_fun f); int sigchain_pop(int sig); +void sigchain_push_common(sigchain_fun f); + #endif /* SIGCHAIN_H */ -- cgit v1.3