remove .fns file for removed host gwen
[build-farm.git] / timelimit.c
index cf0ed01727c451276a6d59c41852999f32e1b6af..7232ecf1610efbd5155759f3a61c24003149aa47 100644 (file)
@@ -1,5 +1,6 @@
 /* run a command with a limited timeout
    tridge@samba.org, June 2005
+   metze@samba.org, March 2006
 
    attempt to be as portable as possible (fighting posix all the way)
 */
 #include <sys/types.h>
 #include <sys/wait.h>
 
+static pid_t child_pid;
+
 static void usage(void)
 {
        printf("usage: timelimit <time> <command>\n");
+       printf("   SIGUSR1 - passes SIGTERM to command's process group\n");
+       printf("   SIGALRM - passes SIGTERM to command's process group\n");
+       printf("             after 5s SIGKILL will be passed and exit(1)\n");
+       printf("   SIGTERM - passes SIGTERM to command's process group\n");
+       printf("             after 1s SIGKILL will be passed and exit(1)\n");
+       printf("   SIGINT  - handled like SIGTERM\n");
+       printf("   SIGQUIT - handled like SIGTERM\n");
 }
 
-static void sig_alrm(int sig)
+static void sig_alrm_kill(int sig)
 {
        fprintf(stderr, "\nMaximum time expired in timelimit - killing\n");
-       kill(0, SIGKILL);
+       kill(-child_pid, SIGKILL);
        exit(1);
 }
 
+static void sig_alrm_term(int sig)
+{
+       fprintf(stderr, "\nMaximum time expired in timelimit - sending TERM To child\n");
+       kill(-child_pid, SIGTERM);
+       signal(SIGALRM, sig_alrm_kill);
+       alarm(5);
+}
+
+static void sig_term(int sig)
+{
+       fprintf(stderr, "\nReceived TERM/INT/QUIT signal\n");
+       kill(-child_pid, SIGTERM);
+       signal(SIGALRM, sig_alrm_kill);
+       alarm(1);
+}
+
+static void sig_usr1(int sig)
+{
+       kill(-child_pid, SIGTERM);
+}
+
+static void new_process_group(void)
+{
+       if (setpgid(0,0) == -1) {
+               perror("setpgid");
+               exit(1);
+       }
+}
+
+
 int main(int argc, char *argv[])
 {
        int maxtime, ret=1;
@@ -33,37 +73,36 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
-#ifdef BSD_SETPGRP
-       if (setpgrp(0,0) == -1) {
-               perror("setpgrp");
-               exit(1);
-       }
-#else
-       if (setpgrp() == -1) {
-               perror("setpgrp");
-               exit(1);
-       }
-#endif
-
        maxtime = atoi(argv[1]);
-       signal(SIGALRM, sig_alrm);
-       alarm(maxtime);
 
-       if (fork() == 0) {
+       child_pid = fork();
+       if (child_pid == 0) {
+               new_process_group();
                execvp(argv[2], argv+2);
                perror(argv[2]);
                exit(1);
        }
 
+       signal(SIGTERM, sig_term);
+       signal(SIGINT,  sig_term);
+       signal(SIGQUIT, sig_term);
+       signal(SIGUSR1, sig_usr1);
+       signal(SIGALRM, sig_alrm_term);
+       alarm(maxtime);
+
        do {
                int status;
                pid_t pid = wait(&status);
                if (pid != -1) {
-                       ret = WEXITSTATUS(status);
+                       if (WIFEXITED(status)) {
+                               ret = WEXITSTATUS(status);
+                       }
                } else if (errno == ECHILD) {
                        break;
                }
        } while (1);
 
+       kill(-child_pid, SIGKILL);
+
        exit(ret);
 }