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