svn commit: r287392 - in stable/10: etc/mtree usr.bin usr.bin/timeout usr.bin/timeout/tests

Baptiste Daroussin bapt at FreeBSD.org
Wed Sep 2 05:45:49 UTC 2015


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 <bapt at FreeBSD.org>
  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod at FreeBSD.org>
  * 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);
 }


More information about the svn-src-all mailing list