[Python-checkins] cpython: Issue #23646: Enhance precision of time.sleep() and socket timeout when

victor.stinner python-checkins at python.org
Fri Mar 20 02:01:57 CET 2015


https://hg.python.org/cpython/rev/9882cc2efd36
changeset: 95081:9882cc2efd36
user: Victor Stinner <victor.stinner at gmail.com>
date: Fri Mar 20 01:42:20 2015 +0100
summary:
 Issue #23646: Enhance precision of time.sleep() and socket timeout when
interrupted by a signal
Add a new _PyTime_AddDouble() function and remove _PyTime_ADD_SECONDS() macro.
The _PyTime_ADD_SECONDS only supported an integer number of seconds, the
_PyTime_AddDouble() has subsecond resolution.
files:
 Include/pytime.h | 12 +++++-------
 Lib/test/eintrdata/eintr_tester.py | 7 ++-----
 Modules/socketmodule.c | 2 +-
 Modules/timemodule.c | 4 ++--
 Python/pytime.c | 17 +++++++++++++++++
 5 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/Include/pytime.h b/Include/pytime.h
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -41,13 +41,6 @@
 _PyTime_timeval *tp,
 _Py_clock_info_t *info);
 
-#define _PyTime_ADD_SECONDS(tv, interval) \
-do { \
- tv.tv_usec += (long) (((long) interval - interval) * 1000000); \
- tv.tv_sec += (time_t) interval + (time_t) (tv.tv_usec / 1000000); \
- tv.tv_usec %= 1000000; \
-} while (0)
-
 #define _PyTime_INTERVAL(tv_start, tv_end) \
 ((tv_end.tv_sec - tv_start.tv_sec) + \
 (tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
@@ -109,6 +102,11 @@
 _PyTime_timeval *tp,
 _Py_clock_info_t *info);
 
+/* Add interval seconds to tv */
+PyAPI_FUNC(void)
+_PyTime_AddDouble(_PyTime_timeval *tv, double interval,
+ _PyTime_round_t round);
+
 /* Initialize time.
 Return 0 on success, raise an exception and return -1 on error. */
 PyAPI_FUNC(int) _PyTime_Init(void);
diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py
--- a/Lib/test/eintrdata/eintr_tester.py
+++ b/Lib/test/eintrdata/eintr_tester.py
@@ -258,13 +258,10 @@
 
 def test_sleep(self):
 t0 = time.monotonic()
- # time.sleep() may retry when interrupted by a signal
- time.sleep(2)
+ time.sleep(self.sleep_time)
 signal.alarm(0)
 dt = time.monotonic() - t0
- # Tolerate a difference 100 ms: on Windows, time.monotonic() has
- # a resolution of 15.6 ms or greater
- self.assertGreaterEqual(dt, 1.9)
+ self.assertGreaterEqual(dt, self.sleep_time)
 
 
 def test_main():
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -687,7 +687,7 @@
 if (has_timeout) { \
 _PyTime_monotonic(&now); \
 deadline = now; \
- _PyTime_ADD_SECONDS(deadline, s->sock_timeout); \
+ _PyTime_AddDouble(&deadline, s->sock_timeout, _PyTime_ROUND_UP); \
 } \
 while (1) { \
 errno = 0; \
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -1399,14 +1399,14 @@
 #endif
 
 _PyTime_monotonic(&deadline);
- _PyTime_ADD_SECONDS(deadline, secs);
+ _PyTime_AddDouble(&deadline, secs, _PyTime_ROUND_UP);
 
 do {
 #ifndef MS_WINDOWS
 frac = fmod(secs, 1.0);
 secs = floor(secs);
 timeout.tv_sec = (long)secs;
- timeout.tv_usec = (long)(frac*1000000.0);
+ timeout.tv_usec = (long)(frac*1e6);
 
 Py_BEGIN_ALLOW_THREADS
 err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
diff --git a/Python/pytime.c b/Python/pytime.c
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -367,6 +367,23 @@
 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
 }
 
+void
+_PyTime_AddDouble(_PyTime_timeval *tv, double interval, _PyTime_round_t round)
+{
+ _PyTime_timeval tv2;
+ double frac;
+
+ frac = fmod(interval, 1.0);
+ interval = floor(interval);
+ tv2.tv_sec = (long)interval;
+ tv2.tv_usec = (long)(frac*1e6);
+
+ tv->tv_sec += tv2.tv_sec;
+ tv->tv_usec += tv2.tv_usec;
+ tv->tv_sec += (time_t)(tv->tv_usec / 1000000);
+ tv->tv_usec %= 1000000;
+}
+
 int
 _PyTime_Init(void)
 {
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /