xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/killme_after.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1*33881f77Schristos /*	$NetBSD: killme_after.c,v 1.2 2020/03/18 19:05:21 christos Exp $	*/
241fbaed0Stron 
341fbaed0Stron /*++
441fbaed0Stron /* NAME
541fbaed0Stron /*	killme_after 3
641fbaed0Stron /* SUMMARY
741fbaed0Stron /*	programmed death
841fbaed0Stron /* SYNOPSIS
941fbaed0Stron /*	#include <killme_after.h>
1041fbaed0Stron /*
1141fbaed0Stron /*	void	killme_after(seconds)
1241fbaed0Stron /*	unsigned int seconds;
1341fbaed0Stron /* DESCRIPTION
1441fbaed0Stron /*	The killme_after() function does a best effort to terminate
1541fbaed0Stron /*	the process after the specified time, should it still exist.
1641fbaed0Stron /*	It is meant to be used in a signal handler, as an insurance
1741fbaed0Stron /*	against getting stuck somewhere while preparing for exit.
1841fbaed0Stron /* DIAGNOSTICS
1941fbaed0Stron /*	None. This routine does a best effort, damn the torpedoes.
2041fbaed0Stron /* LICENSE
2141fbaed0Stron /* .ad
2241fbaed0Stron /* .fi
2341fbaed0Stron /*	The Secure Mailer license must be distributed with this software.
2441fbaed0Stron /* AUTHOR(S)
2541fbaed0Stron /*	Wietse Venema
2641fbaed0Stron /*	IBM T.J. Watson Research
2741fbaed0Stron /*	P.O. Box 704
2841fbaed0Stron /*	Yorktown Heights, NY 10598, USA
29f3bc92a4Schristos /*
30f3bc92a4Schristos /*	Wietse Venema
31f3bc92a4Schristos /*	Google, Inc.
32f3bc92a4Schristos /*	111 8th Avenue
33f3bc92a4Schristos /*	New York, NY 10011, USA
3441fbaed0Stron /*--*/
3541fbaed0Stron 
3641fbaed0Stron /* System library. */
3741fbaed0Stron 
3841fbaed0Stron #include <sys_defs.h>
3941fbaed0Stron #include <signal.h>
4041fbaed0Stron #include <unistd.h>
4141fbaed0Stron 
4241fbaed0Stron /* Utility library. */
4341fbaed0Stron 
4441fbaed0Stron #include <killme_after.h>
4541fbaed0Stron 
4641fbaed0Stron /* killme_after - self-assured death */
4741fbaed0Stron 
killme_after(unsigned int seconds)4841fbaed0Stron void    killme_after(unsigned int seconds)
4941fbaed0Stron {
5041fbaed0Stron     struct sigaction sig_action;
5141fbaed0Stron 
5241fbaed0Stron     /*
5341fbaed0Stron      * Schedule an ALARM signal, and make sure the signal will be delivered
5441fbaed0Stron      * even if we are being called from a signal handler and SIGALRM delivery
5541fbaed0Stron      * is blocked.
56f3bc92a4Schristos      *
57f3bc92a4Schristos      * Undocumented: when a process runs with PID 1, Linux won't deliver a
58f3bc92a4Schristos      * signal unless the process specifies a handler (i.e. SIG_DFL is treated
59f3bc92a4Schristos      * as SIG_IGN). Conveniently, _exit() can be used directly as a signal
60f3bc92a4Schristos      * handler. This changes the wait status that a parent would see, but in
61f3bc92a4Schristos      * the case of "init" mode on Linux, no-one would care.
6241fbaed0Stron      */
6341fbaed0Stron     alarm(0);
6441fbaed0Stron     sigemptyset(&sig_action.sa_mask);
6541fbaed0Stron     sig_action.sa_flags = 0;
66f3bc92a4Schristos     sig_action.sa_handler = (getpid() == 1 ? _exit : SIG_DFL);
6741fbaed0Stron     sigaction(SIGALRM, &sig_action, (struct sigaction *) 0);
6841fbaed0Stron     alarm(seconds);
6941fbaed0Stron     sigaddset(&sig_action.sa_mask, SIGALRM);
7041fbaed0Stron     sigprocmask(SIG_UNBLOCK, &sig_action.sa_mask, (sigset_t *) 0);
7141fbaed0Stron }
72