bin/139345: handle SIGINFO in sleep(1), etc. [patch]

Mikhail T. mi+thun at aldan.algebra.com
Sat Oct 24 17:20:05 UTC 2009


The following reply was made to PR bin/139345; it has been noted by GNATS.

From: "Mikhail T." <mi+thun at aldan.algebra.com>
To: FreeBSD-gnats-submit at FreeBSD.org, freebsd-bugs at 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--


More information about the freebsd-bugs mailing list