6d7afb333e3b50a2fe2d240fea1b8f2708d20244
[awesomized/libmemcached] / memcached / timedrun.c
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
12 static void caught_signal(int which)
13 {
14 caught = which;
15 }
16
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
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
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 }