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