Author: Armin Rigo <[email protected]>
Branch: py3.5-eintr-pep475
Changeset: r88878:b98fafbb5f1c
Date: 2016-12-04 12:40 +0100
http://bitbucket.org/pypy/pypy/changeset/b98fafbb5f1c/

Log:    pep475ify time.sleep()

diff --git a/pypy/interpreter/timeutils.py b/pypy/interpreter/timeutils.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/timeutils.py
@@ -0,0 +1,11 @@
+"""
+Access to the time module's high-resolution monotonic clock
+"""
+
+def monotonic(space):
+    from pypy.module.time import interp_time
+    if interp_time.HAS_MONOTONIC:
+        w_res = interp_time.monotonic(space)
+    else:
+        w_res = interp_time.gettimeofday(space)
+    return space.float_w(w_res)   # xxx back and forth
diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -2,6 +2,7 @@
 from rpython.rtyper.lltypesystem import rffi
 from pypy.interpreter.error import OperationError, oefmt, strerror as 
_strerror, exception_from_saved_errno
 from pypy.interpreter.gateway import unwrap_spec
+from pypy.interpreter import timeutils
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rlib.rarithmetic import intmask, r_ulonglong, r_longfloat, widen
 from rpython.rlib.rtime import (GETTIMEOFDAY_NO_TZ, TIMEVAL,
@@ -438,12 +439,31 @@
     return _strerror(errno)
 
 if sys.platform != 'win32':
+    from errno import EINTR
+    from rpython.rlib.rtime import c_select
+
     @unwrap_spec(secs=float)
     def sleep(space, secs):
         if secs < 0:
             raise oefmt(space.w_ValueError,
                         "sleep length must be non-negative")
-        rtime.sleep(secs)
+        end_time = timeutils.monotonic(space) + secs
+        while True:
+            void = lltype.nullptr(rffi.VOIDP.TO)
+            with lltype.scoped_alloc(TIMEVAL) as t:
+                frac = math.fmod(secs, 1.0)
+                rffi.setintfield(t, 'c_tv_sec', int(secs))
+                rffi.setintfield(t, 'c_tv_usec', int(frac*1000000.0))
+
+                res = rffi.cast(rffi.LONG, c_select(0, void, void, void, t))
+            if res == 0:
+                break    # normal path
+            if rposix.get_saved_errno() != EINTR:
+                raise exception_from_saved_errno(space, space.w_OSError)
+            secs = end_time - timeutils.monotonic(space)   # retry
+            if secs <= 0.0:
+                break
+
 else:
     from rpython.rlib import rwin32
     from errno import EINTR
@@ -463,6 +483,7 @@
                                    OSError(EINTR, "sleep() interrupted"))
     @unwrap_spec(secs=float)
     def sleep(space, secs):
+        XXX   # review for EINTR / PEP475
         if secs < 0:
             raise oefmt(space.w_ValueError,
                         "sleep length must be non-negative")
diff --git a/pypy/module/time/test/test_time.py 
b/pypy/module/time/test/test_time.py
--- a/pypy/module/time/test/test_time.py
+++ b/pypy/module/time/test/test_time.py
@@ -1,6 +1,6 @@
 class AppTestTime:
     spaceconfig = {
-        "usemodules": ['time', 'struct', 'binascii'],
+        "usemodules": ['time', 'struct', 'binascii', 'signal'],
     }
 
     def test_attributes(self):
@@ -394,3 +394,23 @@
             assert info.resolution > 0.0
             assert info.resolution <= 1.0
             assert isinstance(info.adjustable, bool)
+
+    def test_pep475_retry_sleep(self):
+        import time
+        import _signal as signal
+        signalled = []
+
+        def foo(*args):
+            signalled.append("ALARM")
+
+        signal.signal(signal.SIGALRM, foo)
+        try:
+            t1 = time.time()
+            signal.alarm(1)
+            time.sleep(3.0)
+            t2 = time.time()
+        finally:
+            signal.signal(signal.SIGALRM, signal.SIG_DFL)
+
+        assert signalled != []
+        assert t2 - t1 > 2.99
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to