diff options
-rw-r--r-- | Doc/library/time.rst | 4 | ||||
-rw-r--r-- | Lib/test/eintrdata/eintr_tester.py | 17 | ||||
-rw-r--r-- | Lib/test/test_signal.py | 17 | ||||
-rw-r--r-- | Modules/timemodule.c | 118 |
4 files changed, 57 insertions, 99 deletions
diff --git a/Doc/library/time.rst b/Doc/library/time.rst index f5e08c5..6bfd521 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -350,10 +350,6 @@ The module defines the following functions and data items: requested by an arbitrary amount because of the scheduling of other activity in the system. - .. versionchanged:: 3.5 - The function now sleeps at least *secs* even if the sleep is interrupted - by a signal (see :pep:`475` for the rationale). - .. function:: strftime(format[, t]) diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py index 8547576..40dca84 100644 --- a/Lib/test/eintrdata/eintr_tester.py +++ b/Lib/test/eintrdata/eintr_tester.py @@ -252,23 +252,8 @@ class SocketEINTRTest(EINTRBaseTest): lambda path: os.close(os.open(path, os.O_WRONLY))) -@unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()") -class TimeEINTRTest(EINTRBaseTest): - """ EINTR tests for the time module. """ - - def test_sleep(self): - t0 = time.monotonic() - time.sleep(2) - signal.alarm(0) - dt = time.monotonic() - t0 - self.assertGreaterEqual(dt, 1.9) - - def test_main(): - support.run_unittest( - OSEINTRTest, - SocketEINTRTest, - TimeEINTRTest) + support.run_unittest(OSEINTRTest, SocketEINTRTest) if __name__ == "__main__": diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 6ecff9e..774fc80 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -419,20 +419,17 @@ class WakeupSignalTests(unittest.TestCase): TIMEOUT_HALF = 5 signal.alarm(1) - + before_time = time.time() # We attempt to get a signal during the sleep, # before select is called - try: - select.select([], [], [], TIMEOUT_FULL) - except InterruptedError: - pass - else: - raise Exception("select() was not interrupted") - - before_time = time.time() + time.sleep(TIMEOUT_FULL) + mid_time = time.time() + dt = mid_time - before_time + if dt >= TIMEOUT_HALF: + raise Exception("%s >= %s" % (dt, TIMEOUT_HALF)) select.select([read], [], [], TIMEOUT_FULL) after_time = time.time() - dt = after_time - before_time + dt = after_time - mid_time if dt >= TIMEOUT_HALF: raise Exception("%s >= %s" % (dt, TIMEOUT_HALF)) """, signal.SIGALRM) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 0eb78e9..7f5f314 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1386,94 +1386,74 @@ floattime(_Py_clock_info_t *info) static int floatsleep(double secs) { - _PyTime_timeval deadline, monotonic; -#ifndef MS_WINDOWS - struct timeval timeout; +/* XXX Should test for MS_WINDOWS first! */ +#if defined(HAVE_SELECT) && !defined(__EMX__) + struct timeval t; double frac; - 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()) + 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); 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()) { - Py_BEGIN_ALLOW_THREADS - Sleep(0); - Py_END_ALLOW_THREADS - break; - } + if (ul_millis == 0 || !_PyOS_IsMainThread()) + Sleep(ul_millis); else { - hInterruptEvent = _PyOS_SigintEvent(); + DWORD rc; + HANDLE hInterruptEvent = _PyOS_SigintEvent(); ResetEvent(hInterruptEvent); - - Py_BEGIN_ALLOW_THREADS rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE); - Py_END_ALLOW_THREADS - - if (rc != WAIT_OBJECT_0) - break; - - /* WaitForSingleObjectEx() was interrupted by SIGINT */ - - if (PyErr_CheckSignals()) + if (rc == WAIT_OBJECT_0) { + Py_BLOCK_THREADS + errno = EINTR; + PyErr_SetFromErrno(PyExc_OSError); return -1; - - _PyTime_monotonic(&monotonic); - secs = _PyTime_INTERVAL(monotonic, deadline); - if (secs <= 0.0) - break; + } } - } while (1); + Py_END_ALLOW_THREADS + } +#else + /* XXX Can't interrupt this sleep */ + Py_BEGIN_ALLOW_THREADS + sleep((int)secs); + Py_END_ALLOW_THREADS #endif + return 0; } |