"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/timedrun.c" (21 Feb 2022, 2691 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "timedrun.c" see the Fossies "Dox" file reference documentation.

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