Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sleep While cute, the previous version is not really safe.



details:   https://anonhg.NetBSD.org/src/rev/ae423517f037
branches:  trunk
changeset: 996248:ae423517f037
user:      kre <kre%NetBSD.org@localhost>
date:      Sat Jan 26 15:20:50 2019 +0000

description:
While cute, the previous version is not really safe.
After all, a system might want to sleep for several
thousand years on a spaceship headed to a distant
solar system...

So, remove the pause() code, deal with limits on the
range (it is just an int) that can be passed to sleep()
by looping, and do a much better job of checking for
out of range input values.

With this change sleep(1) should work for durations
up to something more than 250 billion years.  It
fails (at startup, with an error) if the requested
duration is beyond what can be handled.

Here no changes at all related to locales and arg
parsing.    Still for another day.

diffstat:

 bin/sleep/sleep.1 |  28 +++++++++++++++--------
 bin/sleep/sleep.c |  63 ++++++++++++++++++++++++++++--------------------------
 2 files changed, 51 insertions(+), 40 deletions(-)

diffs (169 lines):

diff -r 34ac0ab97387 -r ae423517f037 bin/sleep/sleep.1
--- a/bin/sleep/sleep.1 Sat Jan 26 15:19:08 2019 +0000
+++ b/bin/sleep/sleep.1 Sat Jan 26 15:20:50 2019 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sleep.1,v 1.25 2019/01/26 15:19:08 kre Exp $
+.\"    $NetBSD: sleep.1,v 1.26 2019/01/26 15:20:50 kre Exp $
 .\"
 .\" Copyright (c) 1990, 1993, 1994
 .\"    The Regents of the University of California.  All rights reserved.
@@ -61,15 +61,6 @@
 and its use will decrease the probability that
 a shell script will execute properly on another system.
 .Pp
-If the request is for more than a little over 135 years
-.Nm
-will pause forever.
-If the computer is still running when the
-.Nm
-should have terminated,
-.Nm
-will need to be killed by outside intervention.
-.Pp
 When the
 .Dv SIGINFO
 signal is received, an estimate of the number of seconds remaining to
@@ -158,6 +149,21 @@
 command is expected to be
 .St -p1003.2
 compatible.
+.Sh BUGS
+This
+.Nm
+command cannot handle requests for durations
+much longer than about 250 billion years.
+Any such attempt will result in an error,
+and immediate termination.
+It is suggested that when there is a need
+for sleeps exceeding this period, the
+.Nm
+command be executed in a loop, with each
+individual
+.Nm
+invocation limited to 200 billion years
+approximately.
 .Sh HISTORY
 A
 .Nm
@@ -167,3 +173,5 @@
 .Ic seconds
 argument respecting the current locale, was added in
 .Nx 1.3 .
+The ability to sleep for extended periods appeared in
+.Nx 9 .
diff -r 34ac0ab97387 -r ae423517f037 bin/sleep/sleep.c
--- a/bin/sleep/sleep.c Sat Jan 26 15:19:08 2019 +0000
+++ b/bin/sleep/sleep.c Sat Jan 26 15:20:50 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sleep.c,v 1.26 2019/01/26 15:19:08 kre Exp $ */
+/* $NetBSD: sleep.c,v 1.27 2019/01/26 15:20:50 kre Exp $ */
 
 /*
  * Copyright (c) 1988, 1993, 1994
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)sleep.c    8.3 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: sleep.c,v 1.26 2019/01/26 15:19:08 kre Exp $");
+__RCSID("$NetBSD: sleep.c,v 1.27 2019/01/26 15:20:50 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -109,6 +109,8 @@
         * into the floating point conversion path if the input
         * is hex (the 'x' in 0xA is not a digit).  Then if
         * strtod() handles hex (on NetBSD it does) so will we.
+        * That path is also taken for scientific notation (1.2e+3)
+        * and when the input is simply nonsense.
         */
        fracflag = 0;
        arg = *argv;
@@ -132,19 +134,21 @@
                        val = strtod_l(arg, &temp, LC_C_LOCALE);
                if (val < 0 || temp == arg || *temp != '\0')
                        usage();
+
                ival = floor(val);
                fval = (1000000000 * (val-ival));
-               if (ival  >= (double)UINT_MAX)
-                       ntime.tv_sec = (double)UINT_MAX;
-               else
-                       ntime.tv_sec = ival;
+               ntime.tv_sec = ival;
+               if ((double)ntime.tv_sec != ival)
+                       errx(1, "requested delay (%s) out of range", arg);
                ntime.tv_nsec = fval;
+
                if (ntime.tv_sec == 0 && ntime.tv_nsec == 0)
                        return EXIT_SUCCESS;    /* was 0.0 or underflowed */
        } else {
                ntime.tv_sec = strtol(arg, &temp, 10);
                if (ntime.tv_sec < 0 || temp == arg || *temp != '\0')
                        usage();
+
                if (ntime.tv_sec == 0)
                        return EXIT_SUCCESS;
                ntime.tv_nsec = 0;
@@ -166,28 +170,21 @@
                        } else
                                err(EXIT_FAILURE, "nanosleep failed");
                }
-       } else {
-               delay = (unsigned long)ntime.tv_sec;
+       } else while (ntime.tv_sec > 0) {
+               delay = (unsigned int)ntime.tv_sec;
+
+               if ((time_t)delay != ntime.tv_sec || delay > 30 * 86400)
+                       delay = 30 * 86400;
 
-               if ((time_t)delay != ntime.tv_sec ||
-                   delay > UINT_MAX - 86400) {
-                       for (;;) {
-                               pause();
-                               if (report_requested) {
-                                       warnx("Waiting for the end of time");
-                                       report_requested = 0;
-                               } else
-                                       break;
-                       }
-               } else {
-                       while ((delay = sleep(delay)) != 0) {
-                               if (report_requested) {
-                                       report((time_t)delay, original, "");
-                                       report_requested = 0;
-                               } else
-                                       break;
-                       }
-               }
+               ntime.tv_sec -= delay;
+               delay = sleep(delay);
+               ntime.tv_sec += delay;
+
+               if (delay != 0 && report_requested) {
+                       report(ntime.tv_sec, original, "");
+                       report_requested = 0;
+               } else
+                       break;
        }
 
        return EXIT_SUCCESS;
@@ -202,10 +199,16 @@
                warnx("In the final moments of the original"
                    " %ld%s second%s", (long)original, msg,
                    original == 1 && *msg == '\0' ? "" : "s");
-       else
+       else if (remain < 2000)
                warnx("Between %ld and %ld seconds left"
-                   " out of the original %ld%s",
-                   remain, remain + 1, (long)original, msg);
+                   " out of the original %g%s",
+                   remain, remain + 1, (double)original, msg);
+       else if ((original - remain) < 100000 && (original-remain) < original/8)
+               warnx("Have waited only %d seconds of the original %g",
+                       (int)(original - remain), (double)original);
+       else
+               warnx("Approximately %g seconds left out of the original %g",
+                       (double)remain, (double)original);
 }
 
 static void



Home | Main Index | Thread Index | Old Index