Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/nanosleep.c @ 12328:bf3fd58aaf19
nanosleep: improve port to mingw
test-nanosleep failed to link, and exposed a need for argument
validation when nanosleep is missing.
* lib/nanosleep.c (rpl_nanosleep): Reject invalid arguments.
* m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Incorporate LIBSOCKET into
LIB_NANOSLEEP, but only when needed.
* modules/select (Link): Document LIBSOCKET.
* m4/select.m4 (gl_FUNC_SELECT): Ensure LIBSOCKET is defined early
enough.
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Wed, 18 Nov 2009 22:14:39 -0700 |
parents | 9e07d6d6ed00 |
children | e8d2c6fc33ad |
rev | line source |
---|---|
2052 | 1 /* Provide a replacement for the POSIX nanosleep function. |
6795
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
2 |
12327
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
3 Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008, 2009 |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
4 Free Software Foundation, Inc. |
2052 | 5 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8146
diff
changeset
|
6 This program is free software: you can redistribute it and/or modify |
2052 | 7 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8146
diff
changeset
|
8 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8146
diff
changeset
|
9 (at your option) any later version. |
2052 | 10 |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8146
diff
changeset
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
2052 | 18 |
19 /* written by Jim Meyering */ | |
20 | |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
7298
diff
changeset
|
21 #include <config.h> |
2270 | 22 |
8146
b31580167c2b
New module 'time', so that apps can include <time.h> as per
Paul Eggert <eggert@cs.ucla.edu>
parents:
7897
diff
changeset
|
23 #include <time.h> |
2270 | 24 |
12327
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
25 #include "intprops.h" |
10230
54813304edd2
Use sigaction module rather than signal().
Eric Blake <ebb9@byu.net>
parents:
10227
diff
changeset
|
26 #include "sig-handler.h" |
12327
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
27 #include "verify.h" |
7897
b7a83a69ac23
* MODULES.html.sh (Support for systems lacking POSIX:2001): New
Paul Eggert <eggert@cs.ucla.edu>
parents:
7302
diff
changeset
|
28 |
5159 | 29 #include <stdbool.h> |
2053 | 30 #include <stdio.h> |
7298
6948138d9f3a
* nanosleep.c: Include <sys/types.h> before sys/select.h, to avoid
Jim Meyering <jim@meyering.net>
parents:
7237
diff
changeset
|
31 #include <sys/types.h> |
10227 | 32 #include <sys/select.h> |
2053 | 33 #include <signal.h> |
2052 | 34 |
7897
b7a83a69ac23
* MODULES.html.sh (Support for systems lacking POSIX:2001): New
Paul Eggert <eggert@cs.ucla.edu>
parents:
7302
diff
changeset
|
35 #include <sys/time.h> |
2057 | 36 #include <errno.h> |
37 | |
6275 | 38 #include <unistd.h> |
2056 | 39 |
8146
b31580167c2b
New module 'time', so that apps can include <time.h> as per
Paul Eggert <eggert@cs.ucla.edu>
parents:
7897
diff
changeset
|
40 #undef nanosleep |
b31580167c2b
New module 'time', so that apps can include <time.h> as per
Paul Eggert <eggert@cs.ucla.edu>
parents:
7897
diff
changeset
|
41 |
7237
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
42 enum { BILLION = 1000 * 1000 * 1000 }; |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
43 |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
44 #if HAVE_BUG_BIG_NANOSLEEP |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
45 |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
46 int |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
47 rpl_nanosleep (const struct timespec *requested_delay, |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
48 struct timespec *remaining_delay) |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
49 { |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
50 /* nanosleep mishandles large sleeps due to internal overflow |
12327
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
51 problems. The worst known case of this is cygwin 1.5.x, which |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
52 can't sleep more than 49.7 days (2**32 milliseconds). Solve this |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
53 by breaking the sleep up into smaller chunks. Verify that time_t |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
54 is large enough. */ |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
55 verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60); |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
56 const time_t limit = 49 * 24 * 60 * 60; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
57 time_t seconds = requested_delay->tv_sec; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
58 struct timespec intermediate; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
59 intermediate.tv_nsec = 0; |
7237
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
60 |
12327
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
61 while (limit < seconds) |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
62 { |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
63 int result; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
64 intermediate.tv_sec = limit; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
65 result = nanosleep (&intermediate, remaining_delay); |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
66 seconds -= limit; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
67 if (result) |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
68 { |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
69 if (remaining_delay) |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
70 { |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
71 remaining_delay->tv_sec += seconds; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
72 remaining_delay->tv_nsec += requested_delay->tv_nsec; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
73 if (BILLION <= requested_delay->tv_nsec) |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
74 { |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
75 remaining_delay->tv_sec++; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
76 remaining_delay->tv_nsec -= BILLION; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
77 } |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
78 } |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
79 return result; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
80 } |
7237
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
81 } |
12327
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
82 intermediate.tv_sec = seconds; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
83 intermediate.tv_nsec = requested_delay->tv_nsec; |
9e07d6d6ed00
nanosleep: work around cygwin bug
Eric Blake <ebb9@byu.net>
parents:
11110
diff
changeset
|
84 return nanosleep (&intermediate, remaining_delay); |
7237
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
85 } |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
86 |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
87 #else |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
88 |
2687
34703e371994
(SIGCONT): Define if not already defined.
Jim Meyering <jim@meyering.net>
parents:
2341
diff
changeset
|
89 /* Some systems (MSDOS) don't have SIGCONT. |
34703e371994
(SIGCONT): Define if not already defined.
Jim Meyering <jim@meyering.net>
parents:
2341
diff
changeset
|
90 Using SIGTERM here turns the signal-handling code below |
34703e371994
(SIGCONT): Define if not already defined.
Jim Meyering <jim@meyering.net>
parents:
2341
diff
changeset
|
91 into a no-op on such systems. */ |
7237
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
92 # ifndef SIGCONT |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
93 # define SIGCONT SIGTERM |
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
94 # endif |
2687
34703e371994
(SIGCONT): Define if not already defined.
Jim Meyering <jim@meyering.net>
parents:
2341
diff
changeset
|
95 |
5060
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
96 static sig_atomic_t volatile suspended; |
2052 | 97 |
2053 | 98 /* Handle SIGCONT. */ |
99 | |
100 static void | |
101 sighandler (int sig) | |
102 { | |
103 suspended = 1; | |
104 } | |
105 | |
6795
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
106 /* Suspend execution for at least *TS_DELAY seconds. */ |
2052 | 107 |
108 static void | |
2056 | 109 my_usleep (const struct timespec *ts_delay) |
2052 | 110 { |
111 struct timeval tv_delay; | |
112 tv_delay.tv_sec = ts_delay->tv_sec; | |
5060
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
113 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000; |
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
114 if (tv_delay.tv_usec == 1000000) |
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
115 { |
6795
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
116 time_t t1 = tv_delay.tv_sec + 1; |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
117 if (t1 < tv_delay.tv_sec) |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
118 tv_delay.tv_usec = 1000000 - 1; /* close enough */ |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
119 else |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
120 { |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
121 tv_delay.tv_sec = t1; |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
122 tv_delay.tv_usec = 0; |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
123 } |
5060
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
124 } |
5813 | 125 select (0, NULL, NULL, NULL, &tv_delay); |
2052 | 126 } |
127 | |
6795
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
128 /* Suspend execution for at least *REQUESTED_DELAY seconds. The |
9dc5bb3f3359
* lib/nanosleep.c [HAVE_SYS_SELECT_H]: Include <sys/select.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6275
diff
changeset
|
129 *REMAINING_DELAY part isn't implemented yet. */ |
2058 | 130 |
2052 | 131 int |
2270 | 132 rpl_nanosleep (const struct timespec *requested_delay, |
2341 | 133 struct timespec *remaining_delay) |
2052 | 134 { |
5159 | 135 static bool initialized; |
5060
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
136 |
12328
bf3fd58aaf19
nanosleep: improve port to mingw
Eric Blake <ebb9@byu.net>
parents:
12327
diff
changeset
|
137 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) |
bf3fd58aaf19
nanosleep: improve port to mingw
Eric Blake <ebb9@byu.net>
parents:
12327
diff
changeset
|
138 { |
bf3fd58aaf19
nanosleep: improve port to mingw
Eric Blake <ebb9@byu.net>
parents:
12327
diff
changeset
|
139 errno = EINVAL; |
bf3fd58aaf19
nanosleep: improve port to mingw
Eric Blake <ebb9@byu.net>
parents:
12327
diff
changeset
|
140 return -1; |
bf3fd58aaf19
nanosleep: improve port to mingw
Eric Blake <ebb9@byu.net>
parents:
12327
diff
changeset
|
141 } |
bf3fd58aaf19
nanosleep: improve port to mingw
Eric Blake <ebb9@byu.net>
parents:
12327
diff
changeset
|
142 |
2058 | 143 /* set up sig handler */ |
5060
4e59cddb690f
nanosleep merge from coreutils
Paul Eggert <eggert@cs.ucla.edu>
parents:
3767
diff
changeset
|
144 if (! initialized) |
2058 | 145 { |
10232 | 146 struct sigaction oldact; |
2053 | 147 |
2058 | 148 sigaction (SIGCONT, NULL, &oldact); |
10230
54813304edd2
Use sigaction module rather than signal().
Eric Blake <ebb9@byu.net>
parents:
10227
diff
changeset
|
149 if (get_handler (&oldact) != SIG_IGN) |
10232 | 150 { |
151 struct sigaction newact; | |
152 | |
153 newact.sa_handler = sighandler; | |
154 sigemptyset (&newact.sa_mask); | |
155 newact.sa_flags = 0; | |
156 sigaction (SIGCONT, &newact, NULL); | |
157 } | |
5159 | 158 initialized = true; |
2058 | 159 } |
2052 | 160 |
5813 | 161 suspended = 0; |
162 | |
2056 | 163 my_usleep (requested_delay); |
2052 | 164 |
2056 | 165 if (suspended) |
2052 | 166 { |
167 /* Calculate time remaining. */ | |
168 /* FIXME: the code in sleep doesn't use this, so there's no | |
169 rush to implement it. */ | |
2058 | 170 |
171 errno = EINTR; | |
2052 | 172 } |
173 | |
174 /* FIXME: Restore sig handler? */ | |
175 | |
2056 | 176 return suspended; |
2052 | 177 } |
7237
119870bc83d7
Work around a bug in both the Linux and SunOS 64-bit kernels:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6795
diff
changeset
|
178 #endif |