xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/killme_after.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
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