1 /* $NetBSD: killme_after.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */
2
3 /*++
4 /* NAME
5 /* killme_after 3
6 /* SUMMARY
7 /* programmed death
8 /* SYNOPSIS
9 /* #include <killme_after.h>
10 /*
11 /* void killme_after(seconds)
12 /* unsigned int seconds;
13 /* DESCRIPTION
14 /* The killme_after() function does a best effort to terminate
15 /* the process after the specified time, should it still exist.
16 /* It is meant to be used in a signal handler, as an insurance
17 /* against getting stuck somewhere while preparing for exit.
18 /* DIAGNOSTICS
19 /* None. This routine does a best effort, damn the torpedoes.
20 /* LICENSE
21 /* .ad
22 /* .fi
23 /* The Secure Mailer license must be distributed with this software.
24 /* AUTHOR(S)
25 /* Wietse Venema
26 /* IBM T.J. Watson Research
27 /* P.O. Box 704
28 /* Yorktown Heights, NY 10598, USA
29 /*
30 /* Wietse Venema
31 /* Google, Inc.
32 /* 111 8th Avenue
33 /* New York, NY 10011, USA
34 /*--*/
35
36 /* System library. */
37
38 #include <sys_defs.h>
39 #include <signal.h>
40 #include <unistd.h>
41
42 /* Utility library. */
43
44 #include <killme_after.h>
45
46 /* killme_after - self-assured death */
47
killme_after(unsigned int seconds)48 void killme_after(unsigned int seconds)
49 {
50 struct sigaction sig_action;
51
52 /*
53 * Schedule an ALARM signal, and make sure the signal will be delivered
54 * even if we are being called from a signal handler and SIGALRM delivery
55 * is blocked.
56 *
57 * Undocumented: when a process runs with PID 1, Linux won't deliver a
58 * signal unless the process specifies a handler (i.e. SIG_DFL is treated
59 * as SIG_IGN). Conveniently, _exit() can be used directly as a signal
60 * handler. This changes the wait status that a parent would see, but in
61 * the case of "init" mode on Linux, no-one would care.
62 */
63 alarm(0);
64 sigemptyset(&sig_action.sa_mask);
65 sig_action.sa_flags = 0;
66 sig_action.sa_handler = (getpid() == 1 ? _exit : SIG_DFL);
67 sigaction(SIGALRM, &sig_action, (struct sigaction *) 0);
68 alarm(seconds);
69 sigaddset(&sig_action.sa_mask, SIGALRM);
70 sigprocmask(SIG_UNBLOCK, &sig_action.sa_mask, (sigset_t *) 0);
71 }
72