Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Oct 2009 12:57:16 -0400
From:      "Mikhail T." <mi+thun@aldan.algebra.com>
To:        FreeBSD-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org
Subject:   Re: bin/139345: handle SIGINFO in sleep(1), etc. [patch]
Message-ID:  <4AE331EC.2090203@aldan.algebra.com>
In-Reply-To: <200910040600.n94606LR060626@freefall.freebsd.org>
References:  <200910040600.n94606LR060626@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------010206010208030009060605
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

An improved patch...

    -mi


--------------010206010208030009060605
Content-Type: text/plain;
 name="sleep.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="sleep.patch"

Index: sleep.c
===================================================================
RCS file: /home/ncvs/src/bin/sleep/sleep.c,v
retrieving revision 1.20
diff -U 2 -r1.20 sleep.c
--- sleep.c	7 Aug 2005 09:11:38 -0000	1.20
+++ sleep.c	24 Oct 2009 16:54:40 -0000
@@ -43,7 +43,10 @@
 
 #include <ctype.h>
+#include <err.h>
 #include <limits.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sysexits.h>
 #include <time.h>
 #include <unistd.h>
@@ -51,16 +54,22 @@
 void usage(void);
 
+volatile sig_atomic_t	report_requested = 0;
+
+static void
+report_request(int signum __unused)
+{
+	report_requested = 1;
+}
+
 int
 main(int argc, char *argv[])
 {
 	struct timespec time_to_sleep;
-	long l;
+	long l, original;
 	int neg;
 	char *p;
 
-	if (argc != 2) {
+	if (argc != 2)
 		usage();
-		return(1);
-	}
 
 	p = argv[1];
@@ -86,13 +95,15 @@
 	if (isdigit((unsigned char)*p)) {
 		l = strtol(p, &p, 10);
+		/*
+		 * Avoid overflow when `seconds' is huge.  This assumes
+		 * that the maximum value for a time_t is <= INT_MAX.
+		 */
+
 		if (l > INT_MAX) {
-			/*
-			 * Avoid overflow when `seconds' is huge.  This assumes
-			 * that the maximum value for a time_t is <= INT_MAX.
-			 */
 			l = INT_MAX;
 		}
 	} else
 		l = 0;
+
 	time_to_sleep.tv_sec = (time_t)l;
 
@@ -105,12 +116,41 @@
 			if (isdigit((unsigned char)*++p))
 				time_to_sleep.tv_nsec += (*p - '0') * l;
+			else if(*p != '\0')
+				usage();
 			else
 				break;
 			l /= 10;
 		} while (l);
-	}
+	} else if (*p != '\0')
+		usage();
 
-	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
-		(void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
+	signal(SIGINFO, report_request); /* We don't care if it fails */
+	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) {
+		original = time_to_sleep.tv_sec;
+		while (nanosleep(&time_to_sleep, &time_to_sleep)) {
+			/*
+			 * Reporting does not bother with fractions
+			 * of a second...
+			 */
+			if (report_requested) {
+				warnx("about %ld seconds left"
+				    " out of the original %ld",
+				    time_to_sleep.tv_sec, original);
+				report_requested = 0;
+			} else {
+				/*
+				 * The old implementation would exit here, so
+				 * that's what we are doing too. Removing
+				 * the break below would change the behavior
+				 * to "go back to sleep" -- the time_to_sleep
+				 * already contains the proper values.
+				 */
+				warn("exiting prematurely after"
+				    " %ld of the %ld seconds of sleep",
+				    original-time_to_sleep.tv_sec, original);
+				break;
+			}
+		}
+	}
 
 	return(0);
@@ -123,3 +163,4 @@
 
 	write(STDERR_FILENO, msg, sizeof(msg) - 1);
+	exit(EX_USAGE);
 }

--------------010206010208030009060605--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4AE331EC.2090203>