Author: bapt
Date: Wed Sep  2 05:45:47 2015
New Revision: 287392
URL: https://svnweb.freebsd.org/changeset/base/287392

Log:
  MFC: r268745,r268746,r268747,r268748,r268749,r268861,r268750,r268751,r268763
       r273769,r273771,r276771,r278810
  
  New BSDL timeout(1) utility compatible with GNU timeout
  
  Relnotes:     yes

Added:
  stable/10/usr.bin/timeout/
     - copied from r268745, head/usr.bin/timeout/
  stable/10/usr.bin/timeout/tests/
     - copied from r273771, head/usr.bin/timeout/tests/
Modified:
  stable/10/etc/mtree/BSD.tests.dist
  stable/10/usr.bin/Makefile
  stable/10/usr.bin/timeout/Makefile
  stable/10/usr.bin/timeout/timeout.1
  stable/10/usr.bin/timeout/timeout.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/etc/mtree/BSD.tests.dist
==============================================================================
--- stable/10/etc/mtree/BSD.tests.dist  Wed Sep  2 02:50:41 2015        
(r287391)
+++ stable/10/etc/mtree/BSD.tests.dist  Wed Sep  2 05:45:47 2015        
(r287392)
@@ -323,6 +323,8 @@
                     ..
                 ..
             ..
+            timeout
+            ..
             variables
                 modifier_M
                 ..

Modified: stable/10/usr.bin/Makefile
==============================================================================
--- stable/10/usr.bin/Makefile  Wed Sep  2 02:50:41 2015        (r287391)
+++ stable/10/usr.bin/Makefile  Wed Sep  2 05:45:47 2015        (r287392)
@@ -157,6 +157,7 @@ SUBDIR=     alias \
        tee \
        ${_tests} \
        time \
+       timeout \
        tip \
        top \
        touch \

Modified: stable/10/usr.bin/timeout/Makefile
==============================================================================
--- head/usr.bin/timeout/Makefile       Wed Jul 16 09:55:36 2014        
(r268745)
+++ stable/10/usr.bin/timeout/Makefile  Wed Sep  2 05:45:47 2015        
(r287392)
@@ -1,5 +1,11 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 PROG=  timeout
 
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
 .include <bsd.prog.mk>

Modified: stable/10/usr.bin/timeout/timeout.1
==============================================================================
--- head/usr.bin/timeout/timeout.1      Wed Jul 16 09:55:36 2014        
(r268745)
+++ stable/10/usr.bin/timeout/timeout.1 Wed Sep  2 05:45:47 2015        
(r287392)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 16, 2014
+.Dd Oct 28, 2014
 .Dt TIMEOUT 1
 .Os
 .Sh NAME
@@ -44,12 +44,18 @@
 starts the
 .Ar command
 with its
-.Ar args
-and kills if it is still runs after
-.Ar duration .
+.Ar args.
+If
+.Ar command
+is still running after
+.Ar duration ,
+it is killed.
+By default,
+.Ar SIGTERM.
+is sent.
 .Bl -tag -width "-k time, --kill-after time"
 .It Fl -preserve-status
-Always exist with the same status as
+Always exits with the same status as
 .Ar command
 even if it times out.
 .It Fl -foreground
@@ -57,14 +63,67 @@ Do not propagate timeout to the
 .Ar command
 children.
 .It Fl s Ar sig , Fl -signal Ar sig
-Speficy the signal to send on timeout by default
+Specify the signal to send on timeout.
+By default,
 .Ar SIGTERM .
+is sent.
 .It Fl k Ar time , Fl -kill-after Ar time
-Send a second kill if the
+Send a second kill signal if
 .Ar command
 is still running after
 .Ar time
-seconds after the first signal was sent
+after the first signal was sent.
+.El
+.Sh DURATION FORMAT
+.Ar duration
+and
+.Ar time
+can be integer or decimal numbers.
+Values without unit symbols are interpreted as seconds.
+.Pp
+Supported unit symbols are:
+.Bl -tag -width indent -compact
+.It s
+seconds
+.It m
+minutes
+.It h
+hours
+.It d
+days
+.El
+.Sh EXIT STATUS
+If the timeout was not reached, the exit status of
+.Ar command
+is returned.
+.Pp
+If the timeout was reached and
+.Fl -preserve-status
+is set, the exit status of
+.Ar command
+is returned.
+If
+.Fl -preserve-status
+is not set, an exit status of 124 is returned.
+.Pp
+If
+.Ar command
+exits after receiving a signal, the exit status returned is the signal number
+plus 128.
+.Pp
+If
+.Ar command
+is an invalid command, the exit status returned is 126.
+.Pp
+If
+.Ar command
+is a non existing command, the exit status returned is 127.
+.Pp
+If an invalid parameter is passed to
+.Fl s
+or
+.Fl k ,
+the exit status return is 125.
 .Sh SEE ALSO
-.Xr signal 3 ,
-.Xr kill 1
+.Xr kill 1 ,
+.Xr signal 3

Modified: stable/10/usr.bin/timeout/timeout.c
==============================================================================
--- head/usr.bin/timeout/timeout.c      Wed Jul 16 09:55:36 2014        
(r268745)
+++ stable/10/usr.bin/timeout/timeout.c Wed Sep  2 05:45:47 2015        
(r287392)
@@ -2,7 +2,7 @@
  * Copyright (c) 2014 Baptiste Daroussin <[email protected]>
  * Copyright (c) 2014 Vsevolod Stakhov <[email protected]>
  * All rights reserved.
- *~
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -12,7 +12,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- *~
+ *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
@@ -28,20 +28,20 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
+#include <sys/procctl.h>
 #include <sys/time.h>
 #include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
-#include <getopt.h>
-#include <err.h>
-#include <spawn.h>
-#include <errno.h>
-#include <stdbool.h>
 
 #define EXIT_TIMEOUT 124
 
@@ -53,6 +53,7 @@ static sig_atomic_t sig_ign = 0;
 static void
 usage(void)
 {
+
        fprintf(stderr, "Usage: %s [--signal sig | -s sig] [--preserve-status]"
            " [--kill-after time | -k time] [--foreground] <duration> <command>"
            " <arg ...>\n", getprogname());
@@ -68,7 +69,7 @@ parse_duration(const char *duration)
 
        ret = strtod(duration, &end);
        if (ret == 0 && end == duration)
-               errx(EXIT_FAILURE, "invalid duration");
+               errx(125, "invalid duration");
 
        if (end == NULL || *end == '\0')
                return (ret);
@@ -89,11 +90,11 @@ parse_duration(const char *duration)
                ret *= 60 * 60 * 24;
                break;
        default:
-               errx(EX_USAGE, "invalid duration");
+               errx(125, "invalid duration");
        }
-       
+
        if (ret < 0 || ret >= 100000000UL)
-               errx(EX_USAGE, "invalid duration");
+               errx(125, "invalid duration");
 
        return (ret);
 }
@@ -102,11 +103,11 @@ static int
 parse_signal(const char *str)
 {
        int sig, i;
-       const char *err;
+       const char *errstr;
 
-       sig = strtonum(str, 0, sys_nsig, &err);
+       sig = strtonum(str, 0, sys_nsig, &errstr);
 
-       if (err == NULL)
+       if (errstr == NULL)
                return (sig);
        if (strncasecmp(str, "SIG", 3) == 0)
                str += 3;
@@ -115,8 +116,8 @@ parse_signal(const char *str)
                if (strcasecmp(str, sys_signame[i]) == 0)
                        return (i);
        }
-       
-       errx(EX_USAGE, "invalid signal");
+
+       errx(125, "invalid signal");
 }
 
 static void
@@ -166,13 +167,15 @@ main(int argc, char **argv)
        int foreground, preserve;
        int error, pstat, status;
        int killsig = SIGTERM;
-       int killedwith;
-       pid_t pgid, pid, cpid;
+       pid_t pid, cpid;
        double first_kill;
        double second_kill;
        bool timedout = false;
        bool do_second_kill = false;
+       bool child_done = false;
        struct sigaction signals;
+       struct procctl_reaper_status info;
+       struct procctl_reaper_kill killemall;
        int signums[] = {
                -1,
                SIGTERM,
@@ -185,9 +188,8 @@ main(int argc, char **argv)
 
        foreground = preserve = 0;
        second_kill = 0;
-       cpid = -1;
 
-       struct option longopts[] = {
+       const struct option longopts[] = {
                { "preserve-status", no_argument,       &preserve,    1 },
                { "foreground",      no_argument,       &foreground,  1 },
                { "kill-after",      required_argument, NULL,        'k'},
@@ -225,10 +227,9 @@ main(int argc, char **argv)
        argv++;
 
        if (!foreground) {
-               pgid = setpgid(0,0);
-
-               if (pgid == -1)
-                       err(EX_OSERR, "setpgid()");
+               /* Aquire a reaper */
+               if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1)
+                       err(EX_OSERR, "Fail to acquire the reaper");
        }
 
        memset(&signals, 0, sizeof(signals));
@@ -260,8 +261,12 @@ main(int argc, char **argv)
                signal(SIGTTOU, SIG_DFL);
 
                error = execvp(argv[0], argv);
-               if (error == -1)
-                       err(EX_UNAVAILABLE, "exec()");
+               if (error == -1) {
+                       if (errno == ENOENT)
+                               err(127, "exec(%s)", argv[0]);
+                       else
+                               err(126, "exec(%s)", argv[0]);
+               }
        }
 
        if (sigprocmask(SIG_BLOCK, &signals.sa_mask, NULL) == -1)
@@ -270,29 +275,44 @@ main(int argc, char **argv)
        /* parent continues here */
        set_interval(first_kill);
 
-       sigemptyset(&signals.sa_mask);
-
        for (;;) {
-               killedwith = killsig;
                sigemptyset(&signals.sa_mask);
                sigsuspend(&signals.sa_mask);
 
                if (sig_chld) {
                        sig_chld = 0;
-                       while (((cpid = wait(&status)) < 0) && errno != EINTR)
-                               continue;
 
-                       if (cpid == pid) {
-                               pstat = status;
-                               break;
+                       while ((cpid = waitpid(-1, &status, WNOHANG)) != 0) {
+                               if (cpid < 0) {
+                                       if (errno == EINTR)
+                                               continue;
+                                       else
+                                               break;
+                               } else if (cpid == pid) {
+                                       pstat = status;
+                                       child_done = true;
+                               }
+                       }
+                       if (child_done) {
+                               if (foreground) {
+                                       break;
+                               } else {
+                                       procctl(P_PID, getpid(),
+                                           PROC_REAP_STATUS, &info);
+                                       if (info.rs_children == 0)
+                                               break;
+                               }
                        }
                } else if (sig_alrm) {
                        sig_alrm = 0;
 
                        timedout = true;
-                       if (!foreground)
-                               killpg(pgid, killsig);
-                       else
+                       if (!foreground) {
+                               killemall.rk_sig = killsig;
+                               killemall.rk_flags = 0;
+                               procctl(P_PID, getpid(), PROC_REAP_KILL,
+                                   &killemall);
+                       } else
                                kill(pid, killsig);
 
                        if (do_second_kill) {
@@ -304,9 +324,12 @@ main(int argc, char **argv)
                                break;
 
                } else if (sig_term) {
-                       if (!foreground)
-                               killpg(pgid, killsig);
-                       else
+                       if (!foreground) {
+                               killemall.rk_sig = sig_term;
+                               killemall.rk_flags = 0;
+                               procctl(P_PID, getpid(), PROC_REAP_KILL,
+                                   &killemall);
+                       } else
                                kill(pid, sig_term);
 
                        if (do_second_kill) {
@@ -319,18 +342,21 @@ main(int argc, char **argv)
                }
        }
 
-       while (cpid != pid  && wait(&pstat) == -1) {
+       while (!child_done && wait(&pstat) == -1) {
                if (errno != EINTR)
                        err(EX_OSERR, "waitpid()");
        }
 
+       if (!foreground)
+               procctl(P_PID, getpid(), PROC_REAP_RELEASE, NULL);
+
        if (WEXITSTATUS(pstat))
                pstat = WEXITSTATUS(pstat);
        else if(WIFSIGNALED(pstat))
                pstat = 128 + WTERMSIG(pstat);
 
        if (timedout && !preserve)
-                       pstat = EXIT_TIMEOUT;
+               pstat = EXIT_TIMEOUT;
 
        return (pstat);
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to