summaryrefslogtreecommitdiffstats
path: root/Modules/timemodule.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-03-12 15:19:01 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2015-03-12 15:19:01 (GMT)
commit945c82eea3072b41c09dd7c9cdc75a1f24e0ce59 (patch)
treeb4b9df22ef99c26908dc9d1003f74325a4d5d9fd /Modules/timemodule.c
parentf7cc3fccadae5f2bb764b16808806b7d1849871b (diff)
downloadcpython-945c82eea3072b41c09dd7c9cdc75a1f24e0ce59.zip
cpython-945c82eea3072b41c09dd7c9cdc75a1f24e0ce59.tar.gz
cpython-945c82eea3072b41c09dd7c9cdc75a1f24e0ce59.tar.bz2
test
Diffstat (limited to 'Modules/timemodule.c')
-rw-r--r--Modules/timemodule.c118
1 files changed, 69 insertions, 49 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 7f5f314..0eb78e9 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -1386,74 +1386,94 @@ floattime(_Py_clock_info_t *info)
static int
floatsleep(double secs)
{
-/* XXX Should test for MS_WINDOWS first! */
-#if defined(HAVE_SELECT) && !defined(__EMX__)
- struct timeval t;
+ _PyTime_timeval deadline, monotonic;
+#ifndef MS_WINDOWS
+ struct timeval timeout;
double frac;
- int err;
-
- frac = fmod(secs, 1.0);
- secs = floor(secs);
- t.tv_sec = (long)secs;
- t.tv_usec = (long)(frac*1000000.0);
- Py_BEGIN_ALLOW_THREADS
- err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
- Py_END_ALLOW_THREADS
- if (err != 0) {
-#ifdef EINTR
- if (errno == EINTR) {
- if (PyErr_CheckSignals())
- return -1;
- }
- else
-#endif
- {
- PyErr_SetFromErrno(PyExc_OSError);
+ int err = 0;
+
+ _PyTime_monotonic(&deadline);
+ _PyTime_ADD_SECONDS(deadline, secs);
+
+ while (1) {
+ frac = fmod(secs, 1.0);
+ secs = floor(secs);
+ timeout.tv_sec = (long)secs;
+ timeout.tv_usec = (long)(frac*1000000.0);
+
+ Py_BEGIN_ALLOW_THREADS
+ err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
+ Py_END_ALLOW_THREADS
+
+ if (!(err != 0 && errno == EINTR))
+ break;
+
+ /* select() was interrupted by a signal */
+ if (PyErr_CheckSignals())
return -1;
+
+ _PyTime_monotonic(&monotonic);
+ secs = _PyTime_INTERVAL(monotonic, deadline);
+ if (secs <= 0.0) {
+ err = 0;
+ errno = 0;
+ break;
}
}
-#elif defined(__WATCOMC__) && !defined(__QNX__)
- /* XXX Can't interrupt this sleep */
- Py_BEGIN_ALLOW_THREADS
- delay((int)(secs * 1000 + 0.5)); /* delay() uses milliseconds */
- Py_END_ALLOW_THREADS
-#elif defined(MS_WINDOWS)
- {
- double millisecs = secs * 1000.0;
- unsigned long ul_millis;
+ if (err != 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+#else
+ double millisecs;
+ unsigned long ul_millis;
+ DWORD rc;
+ HANDLE hInterruptEvent;
+
+ _PyTime_monotonic(&deadline);
+ _PyTime_ADD_SECONDS(deadline, secs);
+
+ do {
+ millisecs = secs * 1000.0;
if (millisecs > (double)ULONG_MAX) {
PyErr_SetString(PyExc_OverflowError,
"sleep length is too large");
return -1;
}
- Py_BEGIN_ALLOW_THREADS
+
/* Allow sleep(0) to maintain win32 semantics, and as decreed
* by Guido, only the main thread can be interrupted.
*/
ul_millis = (unsigned long)millisecs;
- if (ul_millis == 0 || !_PyOS_IsMainThread())
- Sleep(ul_millis);
+ if (ul_millis == 0 || !_PyOS_IsMainThread()) {
+ Py_BEGIN_ALLOW_THREADS
+ Sleep(0);
+ Py_END_ALLOW_THREADS
+ break;
+ }
else {
- DWORD rc;
- HANDLE hInterruptEvent = _PyOS_SigintEvent();
+ hInterruptEvent = _PyOS_SigintEvent();
ResetEvent(hInterruptEvent);
+
+ Py_BEGIN_ALLOW_THREADS
rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE);
- if (rc == WAIT_OBJECT_0) {
- Py_BLOCK_THREADS
- errno = EINTR;
- PyErr_SetFromErrno(PyExc_OSError);
+ Py_END_ALLOW_THREADS
+
+ if (rc != WAIT_OBJECT_0)
+ break;
+
+ /* WaitForSingleObjectEx() was interrupted by SIGINT */
+
+ if (PyErr_CheckSignals())
return -1;
- }
+
+ _PyTime_monotonic(&monotonic);
+ secs = _PyTime_INTERVAL(monotonic, deadline);
+ if (secs <= 0.0)
+ break;
}
- Py_END_ALLOW_THREADS
- }
-#else
- /* XXX Can't interrupt this sleep */
- Py_BEGIN_ALLOW_THREADS
- sleep((int)secs);
- Py_END_ALLOW_THREADS
+ } while (1);
#endif
-
return 0;
}