xref: /memcached-1.4.29/timedrun.c (revision 016a87c5)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <signal.h>
5 #include <sys/wait.h>
6 #include <sysexits.h>
7 
8 #include <assert.h>
9 
10 static int caught = 0;
11 
caught_signal(int which)12 static void caught_signal(int which)
13 {
14     caught = which;
15 }
16 
wait_for_process(pid_t pid)17 static int wait_for_process(pid_t pid)
18 {
19     int rv = EX_SOFTWARE;
20     int stats = 0;
21     int i = 0;
22     struct sigaction sig_handler;
23 
24     sig_handler.sa_handler = caught_signal;
25     sig_handler.sa_flags = 0;
26 
27     sigaction(SIGALRM, &sig_handler, NULL);
28     sigaction(SIGHUP, &sig_handler, NULL);
29     sigaction(SIGINT, &sig_handler, NULL);
30     sigaction(SIGTERM, &sig_handler, NULL);
31     sigaction(SIGPIPE, &sig_handler, NULL);
32 
33     /* Loop forever waiting for the process to quit */
34     for (i = 0; ;i++) {
35         pid_t p = waitpid(pid, &stats, 0);
36         if (p == pid) {
37             /* child exited.  Let's get out of here */
38             rv = WIFEXITED(stats) ?
39                 WEXITSTATUS(stats) :
40                 (0x80 | WTERMSIG(stats));
41             break;
42         } else {
43             int sig = 0;
44             switch (i) {
45             case 0:
46                 /* On the first iteration, pass the signal through */
47                 sig = caught > 0 ? caught : SIGTERM;
48                 if (caught == SIGALRM) {
49                    fprintf(stderr, "Timeout.. killing the process\n");
50                 }
51                 break;
52             case 1:
53                 sig = SIGTERM;
54                 break;
55             default:
56                 sig = SIGKILL;
57                 break;
58             }
59             if (kill(pid, sig) < 0) {
60                 /* Kill failed.  Must have lost the process. :/ */
61                 perror("lost child when trying to kill");
62             }
63             /* Wait up to 5 seconds for the pid */
64             alarm(5);
65         }
66     }
67     return rv;
68 }
69 
spawn_and_wait(char ** argv)70 static int spawn_and_wait(char **argv)
71 {
72     int rv = EX_SOFTWARE;
73     pid_t pid = fork();
74 
75     switch (pid) {
76     case -1:
77         perror("fork");
78         rv = EX_OSERR;
79         break; /* NOTREACHED */
80     case 0:
81         execvp(argv[0], argv);
82         perror("exec");
83         rv = EX_SOFTWARE;
84         break; /* NOTREACHED */
85     default:
86         rv = wait_for_process(pid);
87     }
88     return rv;
89 }
90 
main(int argc,char ** argv)91 int main(int argc, char **argv)
92 {
93     int naptime = 0;
94     assert(argc > 2);
95 
96     naptime = atoi(argv[1]);
97     assert(naptime > 0 && naptime < 1800);
98 
99     alarm(naptime);
100 
101     return spawn_and_wait(argv+2);
102 }
103