diff options
Diffstat (limited to 'src/util/killme_after.c')
-rw-r--r-- | src/util/killme_after.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/util/killme_after.c b/src/util/killme_after.c new file mode 100644 index 0000000..34e0434 --- /dev/null +++ b/src/util/killme_after.c @@ -0,0 +1,69 @@ +/*++ +/* NAME +/* killme_after 3 +/* SUMMARY +/* programmed death +/* SYNOPSIS +/* #include <killme_after.h> +/* +/* void killme_after(seconds) +/* unsigned int seconds; +/* DESCRIPTION +/* The killme_after() function does a best effort to terminate +/* the process after the specified time, should it still exist. +/* It is meant to be used in a signal handler, as an insurance +/* against getting stuck somewhere while preparing for exit. +/* DIAGNOSTICS +/* None. This routine does a best effort, damn the torpedoes. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <signal.h> +#include <unistd.h> + +/* Utility library. */ + +#include <killme_after.h> + +/* killme_after - self-assured death */ + +void killme_after(unsigned int seconds) +{ + struct sigaction sig_action; + + /* + * Schedule an ALARM signal, and make sure the signal will be delivered + * even if we are being called from a signal handler and SIGALRM delivery + * is blocked. + * + * Undocumented: when a process runs with PID 1, Linux won't deliver a + * signal unless the process specifies a handler (i.e. SIG_DFL is treated + * as SIG_IGN). Conveniently, _exit() can be used directly as a signal + * handler. This changes the wait status that a parent would see, but in + * the case of "init" mode on Linux, no-one would care. + */ + alarm(0); + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = 0; + sig_action.sa_handler = (getpid() == 1 ? _exit : SIG_DFL); + sigaction(SIGALRM, &sig_action, (struct sigaction *) 0); + alarm(seconds); + sigaddset(&sig_action.sa_mask, SIGALRM); + sigprocmask(SIG_UNBLOCK, &sig_action.sa_mask, (sigset_t *) 0); +} |