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