1 /* process.c -- child process routines for vlock,
2 * the VT locking program for linux
4 * This program is copyright (C) 2007 Frank Benkstein, and is free
5 * software which is freely distributable under the terms of the
6 * GNU General Public License version 2, included as the file COPYING in this
7 * distribution. It is NOT public domain software, and any
8 * redistribution not permitted by the GNU General Public License is
9 * expressly forbidden without prior written permission from
18 #include <sys/resource.h>
24 static void ignore_sigalarm(int __attribute__((unused
)) signum
)
28 bool wait_for_death(pid_t pid
, long sec
, long usec
)
32 struct sigaction oldact
;
33 struct itimerval timer
;
34 struct itimerval otimer
;
37 /* Ignore SIGALRM. The handler must be a real function instead of SIG_IGN
38 * otherwise waitpid() would not get interrupted.
40 * There is a small window here where a previously set alarm might be
42 sigemptyset(&act
.sa_mask
);
43 act
.sa_handler
= ignore_sigalarm
;
45 sigaction(SIGALRM
, &act
, &oldact
);
47 /* Initialize the timer. */
48 timer
.it_value
.tv_sec
= sec
;
49 timer
.it_value
.tv_usec
= usec
;
51 timer
.it_interval
.tv_sec
= 0;
52 timer
.it_interval
.tv_usec
= 0;
55 setitimer(ITIMER_REAL
, &timer
, &otimer
);
57 /* Wait until the child exits or the timer fires. */
58 result
= (waitpid(pid
, &status
, 0) == pid
);
60 /* Possible race condition. If an alarm was set before it may get ignored.
61 * This is probably better than getting killed by our own alarm. */
63 /* Restore the timer. */
64 setitimer(ITIMER_REAL
, &otimer
, NULL
);
66 /* Restore signal handler for SIGALRM. */
67 sigaction(SIGALRM
, &oldact
, NULL
);
72 /* Try hard to kill the given child process. */
73 void ensure_death(pid_t pid
)
77 switch (waitpid(pid
, &status
, WNOHANG
)) {
82 /* Not dead yet. Continue. */
85 /* Already dead. Nothing to do. */
90 (void) kill(pid
, SIGTERM
);
92 /* SIGTERM handler (if any) has 500ms to finish. */
93 if (wait_for_death(pid
, 0, 500000L))
97 (void) kill(pid
, SIGKILL
);
98 /* Child may be stopped. Send SIGCONT just to be sure. */
99 (void) kill(pid
, SIGCONT
);
101 /* Wait until dead. Shouldn't take long. */
102 (void) waitpid(pid
, &status
, 0);
105 /* Close all possibly open file descriptors except STDIN_FILENO, STDOUT_FILENO
106 * and STDERR_FILENO. */
107 void close_all_fds(void)
112 /* Get the maximum number of file descriptors. */
113 if (getrlimit(RLIMIT_NOFILE
, &r
) == 0)
116 /* Hopefully safe default. */
119 /* Close all possibly open file descriptors except STDIN_FILENO,
120 * STDOUT_FILENO and STDERR_FILENO. */
121 for (int i
= 0; i
< maxfd
; i
++) {