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