svn commit: r315723 - in stable/11: . bin/pwait bin/pwait/tests etc/mtree targets/pseudo/tests usr.bin/timeout/tests

Bryan Drewery bdrewery at FreeBSD.org
Wed Mar 22 17:53:28 UTC 2017


Author: bdrewery
Date: Wed Mar 22 17:53:25 2017
New Revision: 315723
URL: https://svnweb.freebsd.org/changeset/base/315723

Log:
  MFC r314886,r314943,r314944:
  
    r314886:
      pwait: Add a -t flag to specify a timeout before exiting, and tests.
    r314943:
      Remove unneeded -x from tests.
    r314944:
      Rename some tests to end in _test.

Added:
  stable/11/bin/pwait/tests/
     - copied from r314886, head/bin/pwait/tests/
  stable/11/bin/pwait/tests/pwait_test.sh
     - copied unchanged from r314944, head/bin/pwait/tests/pwait_test.sh
  stable/11/usr.bin/timeout/tests/timeout_test.sh
     - copied unchanged from r314944, head/usr.bin/timeout/tests/timeout_test.sh
Deleted:
  stable/11/bin/pwait/tests/pwait.sh
  stable/11/usr.bin/timeout/tests/timeout.sh
Modified:
  stable/11/ObsoleteFiles.inc
  stable/11/bin/pwait/Makefile
  stable/11/bin/pwait/pwait.1
  stable/11/bin/pwait/pwait.c
  stable/11/bin/pwait/tests/Makefile
  stable/11/etc/mtree/BSD.tests.dist
  stable/11/targets/pseudo/tests/Makefile.depend
  stable/11/usr.bin/timeout/tests/Makefile
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/ObsoleteFiles.inc
==============================================================================
--- stable/11/ObsoleteFiles.inc	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/ObsoleteFiles.inc	Wed Mar 22 17:53:25 2017	(r315723)
@@ -38,6 +38,9 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20170308: rename some tests
+OLD_FILES+=usr/tests/bin/pwait/pwait
+OLD_FILES+=usr/tests/usr.bin/timeout/timeout
 # 20170214: Four files from ggate tests consolidated into one
 OLD_FILES+=usr/tests/sys/geom/class/gate/1_test
 OLD_FILES+=usr/tests/sys/geom/class/gate/2_test

Modified: stable/11/bin/pwait/Makefile
==============================================================================
--- stable/11/bin/pwait/Makefile	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/bin/pwait/Makefile	Wed Mar 22 17:53:25 2017	(r315723)
@@ -1,6 +1,12 @@
 # $FreeBSD$
 
+.include <src.opts.mk>
+
 PACKAGE=runtime
 PROG=	pwait
 
+.if ${MK_TESTS} != "no"
+SUBDIR+=	tests
+.endif
+
 .include <bsd.prog.mk>

Modified: stable/11/bin/pwait/pwait.1
==============================================================================
--- stable/11/bin/pwait/pwait.1	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/bin/pwait/pwait.1	Wed Mar 22 17:53:25 2017	(r315723)
@@ -32,7 +32,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 1, 2009
+.Dd March 7, 2017
 .Dt PWAIT 1
 .Os
 .Sh NAME
@@ -40,6 +40,7 @@
 .Nd wait for processes to terminate
 .Sh SYNOPSIS
 .Nm
+.Op Fl t Ar duration
 .Op Fl v
 .Ar pid
 \&...
@@ -50,13 +51,36 @@ utility will wait until each of the give
 .Pp
 The following option is available:
 .Bl -tag -width indent
+.It Fl t Ar duration
+If any process is still running after
+.Ar duration ,
+.Nm
+will exit.
+The
+.Ar duration
+value 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
+.El
 .It Fl v
 Print the exit status when each process terminates.
 .El
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 The
 .Nm
-utility returns 0 on success, and >0 if an error occurs.
+utility exits 0 on success, and >0 if an error occurs.
+.Pp
+If the
+.Fl t
+flag is specified and a timeout occurs, the exit status will be 124.
 .Pp
 Invalid pids elicit a warning message but are otherwise ignored.
 .Sh SEE ALSO

Modified: stable/11/bin/pwait/pwait.c
==============================================================================
--- stable/11/bin/pwait/pwait.c	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/bin/pwait/pwait.c	Wed Mar 22 17:53:25 2017	(r315723)
@@ -53,7 +53,7 @@ static void
 usage(void)
 {
 
-	fprintf(stderr, "usage: pwait [-v] pid ...\n");
+	fprintf(stderr, "usage: pwait [-t timeout] [-v] pid ...\n");
 	exit(EX_USAGE);
 }
 
@@ -63,15 +63,46 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
+	struct itimerval itv;
 	int kq;
 	struct kevent *e;
-	int verbose = 0;
+	int tflag, verbose;
 	int opt, nleft, n, i, duplicate, status;
 	long pid;
 	char *s, *end;
+	double timeout;
 
-	while ((opt = getopt(argc, argv, "v")) != -1) {
+	tflag = verbose = 0;
+	memset(&itv, 0, sizeof(itv));
+	while ((opt = getopt(argc, argv, "t:v")) != -1) {
 		switch (opt) {
+		case 't':
+			tflag = 1;
+			errno = 0;
+			timeout = strtod(optarg, &end);
+			if (end == optarg || errno == ERANGE ||
+			    timeout < 0)
+				errx(EX_DATAERR, "timeout value");
+			switch(*end) {
+			case 0:
+			case 's':
+				break;
+			case 'h':
+				timeout *= 60;
+				/* FALLTHROUGH */
+			case 'm':
+				timeout *= 60;
+				break;
+			default:
+				errx(EX_DATAERR, "timeout unit");
+			}
+			if (timeout > 100000000L)
+				errx(EX_DATAERR, "timeout value");
+			itv.it_value.tv_sec = (time_t)timeout;
+			timeout -= (time_t)timeout;
+			itv.it_value.tv_usec =
+			    (suseconds_t)(timeout * 1000000UL);
+			break;
 		case 'v':
 			verbose = 1;
 			break;
@@ -91,7 +122,7 @@ main(int argc, char *argv[])
 	if (kq == -1)
 		err(1, "kqueue");
 
-	e = malloc(argc * sizeof(struct kevent));
+	e = malloc((argc + tflag) * sizeof(struct kevent));
 	if (e == NULL)
 		err(1, "malloc");
 	nleft = 0;
@@ -119,12 +150,30 @@ main(int argc, char *argv[])
 		}
 	}
 
+	if (tflag) {
+		/*
+		 * Explicitly detect SIGALRM so that an exit status of 124
+		 * can be returned rather than 142.
+		 */
+		EV_SET(e + nleft, SIGALRM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
+		if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
+			err(EX_OSERR, "kevent");
+		/* Ignore SIGALRM to not interrupt kevent(2). */
+		signal(SIGALRM, SIG_IGN);
+		if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
+			err(EX_OSERR, "setitimer");
+	}
 	while (nleft > 0) {
-		n = kevent(kq, NULL, 0, e, nleft, NULL);
+		n = kevent(kq, NULL, 0, e, nleft + tflag, NULL);
 		if (n == -1)
 			err(1, "kevent");
-		if (verbose)
-			for (i = 0; i < n; i++) {
+		for (i = 0; i < n; i++) {
+			if (e[i].filter == EVFILT_SIGNAL) {
+				if (verbose)
+					printf("timeout\n");
+				return (124);
+			}
+			if (verbose) {
 				status = e[i].data;
 				if (WIFEXITED(status))
 					printf("%ld: exited with status %d.\n",
@@ -138,7 +187,8 @@ main(int argc, char *argv[])
 					printf("%ld: terminated.\n",
 					    (long)e[i].ident);
 			}
-		nleft -= n;
+			--nleft;
+		}
 	}
 
 	exit(EX_OK);

Modified: stable/11/bin/pwait/tests/Makefile
==============================================================================
--- head/bin/pwait/tests/Makefile	Tue Mar  7 22:16:55 2017	(r314886)
+++ stable/11/bin/pwait/tests/Makefile	Wed Mar 22 17:53:25 2017	(r315723)
@@ -1,5 +1,5 @@
 # $FreeBSD$
 
-ATF_TESTS_SH=	pwait
+ATF_TESTS_SH=	pwait_test
 
 .include <bsd.test.mk>

Copied: stable/11/bin/pwait/tests/pwait_test.sh (from r314944, head/bin/pwait/tests/pwait_test.sh)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/bin/pwait/tests/pwait_test.sh	Wed Mar 22 17:53:25 2017	(r315723, copy of r314944, head/bin/pwait/tests/pwait_test.sh)
@@ -0,0 +1,242 @@
+# $FreeBSD$
+
+atf_test_case basic
+basic_head()
+{
+	atf_set "descr" "Basic tests on pwait(1) utility"
+}
+
+basic_body()
+{
+	sleep 1 &
+	p1=$!
+
+	sleep 5 &
+	p5=$!
+
+	sleep 10 &
+	p10=$!
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout --preserve-status 15 pwait $p1 $p5 $p10
+
+	atf_check \
+		-o empty \
+		-e inline:"kill: $p1: No such process\n" \
+		-s exit:1 \
+		kill -0 $p1
+
+	atf_check \
+		-o empty \
+		-e inline:"kill: $p5: No such process\n" \
+		-s exit:1 \
+		kill -0 $p5
+
+	atf_check \
+		-o empty \
+		-e inline:"kill: $p10: No such process\n" \
+		-s exit:1 \
+		kill -0 $p10
+
+}
+
+basic_cleanup()
+{
+	kill $p1 $p5 $p10 >/dev/null 2>&1
+	wait $p1 $p5 $p10 >/dev/null 2>&1
+}
+
+atf_test_case time_unit
+time_unit_head()
+{
+	atf_set "descr" "Test parsing the timeout unit and value"
+}
+
+time_unit_body()
+{
+	init=1
+
+	atf_check \
+		-o empty \
+		-e inline:"pwait: timeout unit\n" \
+		-s exit:65 \
+		timeout --preserve-status 2 pwait -t 1d $init
+
+	atf_check \
+		-o empty \
+		-e inline:"pwait: timeout unit\n" \
+		-s exit:65 \
+		timeout --preserve-status 2 pwait -t 1d $init
+
+	atf_check \
+		-o empty \
+		-e inline:"pwait: timeout value\n" \
+		-s exit:65 \
+		timeout --preserve-status 2 pwait -t -1 $init
+
+	atf_check \
+		-o empty \
+		-e inline:"pwait: timeout value\n" \
+		-s exit:65 \
+		timeout --preserve-status 2 pwait -t 100000001 $init
+
+	# These long duration cases are expected to timeout from the
+	# timeout utility rather than pwait -t.
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status 2 pwait -t 100000000 $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status 2 pwait -t 1h $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status 2 pwait -t 1.5h $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status 2 pwait -t 1m $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status 2 pwait -t 1.5m $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status 2 pwait -t 0 $init
+
+	# The rest are fast enough that pwait -t is expected to trigger
+	# the timeout.
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 2 pwait -t 1s $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 2 pwait -t 1.5s $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 2 pwait -t 1 $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 2 pwait -t 1.5 $init
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 2 pwait -t 0.5 $init
+}
+
+atf_test_case timeout_trigger_timeout
+timeout_trigger_timeout_head()
+{
+	atf_set "descr" "Test that exceeding the timeout is detected"
+}
+
+timeout_trigger_timeout_body()
+{
+	sleep 10 &
+	p10=$!
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 6.5 pwait -t 5 $p10
+}
+
+timeout_trigger_timeout_cleanup()
+{
+	kill $p10 >/dev/null 2>&1
+	wait $p10 >/dev/null 2>&1
+}
+
+atf_test_case timeout_no_timeout
+timeout_no_timeout_head()
+{
+	atf_set "descr" "Test that not exceeding the timeout continues to wait"
+}
+
+timeout_no_timeout_body()
+{
+	sleep 10 &
+	p10=$!
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout --preserve-status 11.5 pwait -t 12 $p10
+}
+
+timeout_no_timeout_cleanup()
+{
+	kill $p10 >/dev/null 2>&1
+	wait $p10 >/dev/null 2>&1
+}
+
+atf_test_case timeout_many
+timeout_many_head()
+{
+	atf_set "descr" "Test timeout on many processes"
+}
+
+timeout_many_body()
+{
+	sleep 1 &
+	p1=$!
+
+	sleep 5 &
+	p5=$!
+
+	sleep 10 &
+	p10=$!
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout --preserve-status 7.5 pwait -t 6 $p1 $p5 $p10
+}
+
+timeout_many_cleanup()
+{
+	kill $p1 $p5 $p10 >/dev/null 2>&1
+	wait $p1 $p5 $p10 >/dev/null 2>&1
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case basic
+	atf_add_test_case time_unit
+	atf_add_test_case timeout_trigger_timeout
+	atf_add_test_case timeout_no_timeout
+	atf_add_test_case timeout_many
+}

Modified: stable/11/etc/mtree/BSD.tests.dist
==============================================================================
--- stable/11/etc/mtree/BSD.tests.dist	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/etc/mtree/BSD.tests.dist	Wed Mar 22 17:53:25 2017	(r315723)
@@ -626,6 +626,8 @@
         ..
         printf
         ..
+        pwait
+        ..
         sdiff
         ..
         sed

Modified: stable/11/targets/pseudo/tests/Makefile.depend
==============================================================================
--- stable/11/targets/pseudo/tests/Makefile.depend	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/targets/pseudo/tests/Makefile.depend	Wed Mar 22 17:53:25 2017	(r315723)
@@ -307,6 +307,7 @@ DIRDEPS= \
 	usr.bin/mkimg/tests \
 	usr.bin/ncal/tests \
 	usr.bin/printf/tests \
+	usr.bin/pwait/tests \
 	usr.bin/sdiff/tests \
 	usr.bin/sed/tests \
 	usr.bin/sed/tests/regress.multitest.out \

Modified: stable/11/usr.bin/timeout/tests/Makefile
==============================================================================
--- stable/11/usr.bin/timeout/tests/Makefile	Wed Mar 22 17:49:56 2017	(r315722)
+++ stable/11/usr.bin/timeout/tests/Makefile	Wed Mar 22 17:53:25 2017	(r315723)
@@ -1,5 +1,5 @@
 # $FreeBSD$
 
-ATF_TESTS_SH=	timeout
+ATF_TESTS_SH=	timeout_test
 
 .include <bsd.test.mk>

Copied: stable/11/usr.bin/timeout/tests/timeout_test.sh (from r314944, head/usr.bin/timeout/tests/timeout_test.sh)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/usr.bin/timeout/tests/timeout_test.sh	Wed Mar 22 17:53:25 2017	(r315723, copy of r314944, head/usr.bin/timeout/tests/timeout_test.sh)
@@ -0,0 +1,215 @@
+# $FreeBSD$
+
+atf_test_case nominal
+nominal_head()
+{
+	atf_set "descr" "Basic tests on timeout(1) utility"
+}
+
+nominal_body()
+{
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout 5 true
+}
+
+atf_test_case time_unit
+time_unit_head()
+{
+	atf_set "descr" "Test parsing the default time unit"
+}
+
+time_unit_body()
+{
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout 1d true
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout 1h true
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout 1m true
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout 1s true
+}
+
+atf_test_case no_timeout
+no_timeout_head()
+{
+	atf_set "descr" "Test disabled timeout"
+}
+
+no_timeout_body()
+{
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		timeout 0 true
+}
+
+atf_test_case exit_numbers
+exit_numbers_head()
+{
+	atf_set "descr" "Test exit numbers"
+}
+
+exit_numbers_body()
+{
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:2 \
+		-x timeout 5 sh -c \'exit 2\'
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout .1 sleep 1
+
+	# With preserv status exit should be 128 + TERM aka 143
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:143 \
+		timeout --preserve-status .1 sleep 10
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:124 \
+		timeout -s1 -k1 .1 sleep 10
+
+	atf_check \
+		-o empty \
+		-e empty \
+		-s exit:0 \
+		-x sh -c 'trap "" CHLD; exec timeout 10 true'
+}
+
+atf_test_case with_a_child
+with_a_child_head()
+{
+	atf_set "descr" "When starting with a child (coreutils bug#9098)"
+}
+
+with_a_child_body()
+{
+	out=$(sleep .1 & exec timeout .5 sh -c 'sleep 2; echo foo')
+	status=$?
+	test "$out" = "" && test $status = 124 || atf_fail
+
+}
+
+atf_test_case invalid_timeout
+invalid_timeout_head()
+{
+	atf_set "descr" "Invalid timeout"
+}
+
+invalid_timeout_body()
+{
+	atf_check \
+		-o empty \
+		-e inline:"timeout: invalid duration\n" \
+		-s exit:125 \
+		timeout invalid sleep 0
+
+	atf_check \
+		-o empty \
+		-e inline:"timeout: invalid duration\n" \
+		-s exit:125 \
+		timeout --kill-after=invalid 1 sleep 0
+
+	atf_check \
+		-o empty \
+		-e inline:"timeout: invalid duration\n" \
+		-s exit:125 \
+		timeout 42D sleep 0
+
+	atf_check \
+		-o empty \
+		-e inline:"timeout: invalid duration\n" \
+		-s exit:125 \
+		timeout 999999999999999999999999999999999999999999999999999999999999d sleep 0
+
+	atf_check \
+		-o empty \
+		-e inline:"timeout: invalid duration\n" \
+		-s exit:125 \
+		timeout 2.34e+5d sleep 0
+}
+
+atf_test_case invalid_signal
+invalid_signal_head()
+{
+	atf_set "descr" "Invalid signal"
+}
+
+invalid_signal_body()
+{
+	atf_check \
+		-o empty \
+		-e inline:"timeout: invalid signal\n" \
+		-s exit:125 \
+		timeout --signal=invalid 1 sleep 0
+}
+
+atf_test_case invalid_command
+invalid_command_head()
+{
+	atf_set "descr" "Invalid command"
+}
+
+invalid_command_body()
+{
+	atf_check \
+		-o empty \
+		-e inline:"timeout: exec(.): Permission denied\n" \
+		-s exit:126 \
+		timeout 10 .
+}
+
+atf_test_case no_such_command
+no_such_command_head()
+{
+	atf_set "descr" "No such command"
+}
+
+no_such_command_body()
+{
+	atf_check \
+		-o empty \
+		-e inline:"timeout: exec(enoexists): No such file or directory\n" \
+		-s exit:127 \
+		timeout 10 enoexists
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case nominal
+	atf_add_test_case time_unit
+	atf_add_test_case no_timeout
+	atf_add_test_case exit_numbers
+	atf_add_test_case with_a_child
+	atf_add_test_case invalid_timeout
+	atf_add_test_case invalid_signal
+	atf_add_test_case invalid_command
+	atf_add_test_case no_such_command
+}


More information about the svn-src-all mailing list