From owner-freebsd-bugs@FreeBSD.ORG Sun Oct 4 06:00:13 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2B38E106566B for ; Sun, 4 Oct 2009 06:00:13 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id AD86F8FC1D for ; Sun, 4 Oct 2009 06:00:12 +0000 (UTC) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n94606Qk060637 for ; Sun, 4 Oct 2009 06:00:06 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n94606HR060636; Sun, 4 Oct 2009 06:00:06 GMT (envelope-from gnats) Resent-Date: Sun, 4 Oct 2009 06:00:06 GMT Resent-Message-Id: <200910040600.n94606HR060636@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Mikhail T." Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8E22D106566B for ; 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 ; 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 ; 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." To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: bin/139345: handle SIGINFO in sleep(1), etc. [patch] X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: "Mikhail T." List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 04 Oct 2009 06:00:13 -0000 >Number: 139345 >Category: bin >Synopsis: handle SIGINFO in sleep(1), etc. [patch] >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Oct 04 06:00:06 UTC 2009 >Closed-Date: >Last-Modified: >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 ) 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 +#include #include +#include #include #include +#include #include #include @@ -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: >Unformatted: