From mi@aldan.algebra.com  Sun Oct  4 05:58:15 2009
Return-Path: <mi@aldan.algebra.com>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 8E22D106566B
	for <FreeBSD-gnats-submit@freebsd.org>; Sun,  4 Oct 2009 05:58:15 +0000 (UTC)
	(envelope-from mi@aldan.algebra.com)
Received: from aldan.algebra.com (aldan.algebra.com [216.254.65.224])
	by mx1.freebsd.org (Postfix) with ESMTP id 27F338FC08
	for <FreeBSD-gnats-submit@freebsd.org>; Sun,  4 Oct 2009 05:58:14 +0000 (UTC)
Received: from aldan.algebra.com (localhost [127.0.0.1])
	by aldan.algebra.com (8.14.3/8.14.3) with ESMTP id n945wExY034788
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 4 Oct 2009 01:58:14 -0400 (EDT)
	(envelope-from mi@aldan.algebra.com)
Received: (from mi@localhost)
	by aldan.algebra.com (8.14.3/8.14.3/Submit) id n945wEFg034787;
	Sun, 4 Oct 2009 01:58:14 -0400 (EDT)
	(envelope-from mi)
Message-Id: <200910040558.n945wEFg034787@aldan.algebra.com>
Date: Sun, 4 Oct 2009 01:58:14 -0400 (EDT)
From: "Mikhail T." <mi@aldan.algebra.com>
Reply-To: "Mikhail T." <mi@aldan.algebra.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: handle SIGINFO in sleep(1), etc. [patch]
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         139345
>Category:       bin
>Synopsis:       [patch] handle SIGINFO in sleep(1), etc.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kib
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Oct 04 06:00:06 UTC 2009
>Closed-Date:    Sat Aug 21 14:00:27 UTC 2010
>Last-Modified:  Sat Aug 21 14:00:27 UTC 2010
>Originator:     Mikhail T.
>Release:        FreeBSD 7.2-STABLE amd64
>Organization:
Virtual Estates, Inc. (http://libpipe.com/)
>Environment:

>Description:
	The included patch fixes some long-standing problems with sleep(1)
	and adds nice handling of SIGINFO. It will become possible to figure
	out, how much longer it has to sleep, and what was the originally
	requested period:

	mi@aldan:src/bin/sleep (1043) /usr/obj/var/src/bin/sleep/sleep 12
	load: 0.28  cmd: sleep 34753 [running] 0.00u 0.00s 0% 608k
	sleep: about 10 seconds left out of the original 12
	load: 0.28  cmd: sleep 34753 [running] 0.00u 0.00s 0% 680k
	sleep: about 8 seconds left out of the original 12

	this could be very convenient in some situations.

	The minor fixes are:
		* detect non-numeric (or partially non-numeric)
		  time-lengths and treat them as errors, invoking
		  usage(). The current implementation can be invoked
		  as ``sleep meow'' and will simply exit immediately,
		  instead of reporting incorrect usage. The current
		  implementation can also be invoked as ``sleep 11cats''
		  and will simply sleep for 11 seconds, instead of
		  rejecting the invalid argument.
		* whenever exiting due to incorrect usage, exit with
		  the code EX_USAGE (defined as 64 in <sysexits.h>)
		  instead of code 1.
		* warn the user, if sleep is exiting prematurely due
		  to an interruption (other than SIGINFO). Arguably,
		  the program should just go back to sleep for the
		  remainder of the time, but the current implementation
		  does not, so I did not change this aspect...

>How-To-Repeat:
>Fix:

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	4 Oct 2009 05:52:09 -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,40 @@
 			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);
+			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 +162,4 @@
 
 	write(STDERR_FILENO, msg, sizeof(msg) - 1);
+	exit(EX_USAGE);
 }
>Release-Note:
>Audit-Trail:

From: "Mikhail T." <mi+thun@aldan.algebra.com>
To: FreeBSD-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org
Cc:  
Subject: Re: bin/139345: handle SIGINFO in sleep(1), etc. [patch]
Date: Sat, 24 Oct 2009 12:57:16 -0400

 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--

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/139345: commit references a PR
Date: Sat, 31 Jul 2010 14:30:22 +0000 (UTC)

 Author: kib
 Date: Sat Jul 31 14:30:11 2010
 New Revision: 210679
 URL: http://svn.freebsd.org/changeset/base/210679
 
 Log:
   Report the time left for the sleep on SIGINFO.
   Be stricter in the checking of interval specification.
   
   PR:	bin/139345
   MFC after:	3 weeks
 
 Modified:
   head/bin/sleep/sleep.c
 
 Modified: head/bin/sleep/sleep.c
 ==============================================================================
 --- head/bin/sleep/sleep.c	Sat Jul 31 14:26:10 2010	(r210678)
 +++ head/bin/sleep/sleep.c	Sat Jul 31 14:30:11 2010	(r210679)
 @@ -42,26 +42,34 @@ static char sccsid[] = "@(#)sleep.c	8.3 
  __FBSDID("$FreeBSD$");
  
  #include <ctype.h>
 +#include <err.h>
  #include <limits.h>
 +#include <signal.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <time.h>
  #include <unistd.h>
  
 -void usage(void);
 +static void usage(void);
 +
 +static volatile sig_atomic_t report_requested;
 +static void
 +report_request(int signo __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];
  
 @@ -74,10 +82,8 @@ main(int argc, char *argv[])
  	if (*p == '-') {
  		neg = 1;
  		++p;
 -		if (!isdigit((unsigned char)*p) && *p != '.') {
 +		if (!isdigit((unsigned char)*p) && *p != '.')
  			usage();
 -			return(1);
 -		}
  	}
  	else if (*p == '+')
  		++p;
 @@ -85,13 +91,13 @@ main(int argc, char *argv[])
  	/* Calculate seconds. */
  	if (isdigit((unsigned char)*p)) {
  		l = strtol(p, &p, 10);
 -		if (l > INT_MAX) {
 -			/*
 -			 * Avoid overflow when `seconds' is huge.  This assumes
 -			 * that the maximum value for a time_t is <= INT_MAX.
 -			 */
 +
 +		/*
 +		 * Avoid overflow when `seconds' is huge.  This assumes
 +		 * that the maximum value for a time_t is <= INT_MAX.
 +		 */
 +		if (l > INT_MAX)
  			l = INT_MAX;
 -		}
  	} else
  		l = 0;
  	time_to_sleep.tv_sec = (time_t)l;
 @@ -110,16 +116,38 @@ main(int argc, char *argv[])
  		} while (l);
  	}
  
 -	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
 -		(void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
 +	/* Skip over the trailing whitespace. */
 +	while (isspace((unsigned char)*p))
 +		++p;
 +	if (*p != '\0')
 +		usage();
 +
 +	signal(SIGINFO, report_request);
 +	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) != 0) {
 +			if (report_requested) {
 +				/*
 +				 * Reporting does not bother with
 +				 * fractions of a second...
 +				 */
 +				warnx("about %ld second(s) left"
 +				    " out of the original %ld",
 +				    time_to_sleep.tv_sec, original);
 +				report_requested = 0;
 +			} else
 +				break;
 +		}
 +	}
  
 -	return(0);
 +	return (0);
  }
  
 -void
 +static void
  usage(void)
  {
 -	const char msg[] = "usage: sleep seconds\n";
 +	static const char msg[] = "usage: sleep seconds\n";
  
  	write(STDERR_FILENO, msg, sizeof(msg) - 1);
 +	exit(1);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
Responsible-Changed-From-To: freebsd-bugs->kib 
Responsible-Changed-By: vwe 
Responsible-Changed-When: Sat Aug 21 13:58:53 UTC 2010 
Responsible-Changed-Why:  
mfc reminder 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139345 
State-Changed-From-To: open->closed 
State-Changed-By: kib 
State-Changed-When: Sat Aug 21 13:59:45 UTC 2010 
State-Changed-Why:  
Merged to stable/8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139345 
>Unformatted:
