Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9a8089b

Browse files
committed
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.
1 parent 4fa99cd commit 9a8089b

5 files changed

Lines changed: 27 additions & 15 deletions

File tree

Include/pytime.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,6 @@ PyAPI_FUNC(int) _PyTime_gettimeofday_info(
4141
_PyTime_timeval *tp,
4242
_Py_clock_info_t *info);
4343

44-
#define _PyTime_ADD_SECONDS(tv, interval) \
45-
do { \
46-
tv.tv_usec += (long) (((long) interval - interval) * 1000000); \
47-
tv.tv_sec += (time_t) interval + (time_t) (tv.tv_usec / 1000000); \
48-
tv.tv_usec %= 1000000; \
49-
} while (0)
50-
5144
#define _PyTime_INTERVAL(tv_start, tv_end) \
5245
((tv_end.tv_sec - tv_start.tv_sec) + \
5346
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
@@ -109,6 +102,11 @@ PyAPI_FUNC(int) _PyTime_monotonic_info(
109102
_PyTime_timeval *tp,
110103
_Py_clock_info_t *info);
111104

105+
/* Add interval seconds to tv */
106+
PyAPI_FUNC(void)
107+
_PyTime_AddDouble(_PyTime_timeval *tv, double interval,
108+
_PyTime_round_t round);
109+
112110
/* Initialize time.
113111
Return 0 on success, raise an exception and return -1 on error. */
114112
PyAPI_FUNC(int) _PyTime_Init(void);

Lib/test/eintrdata/eintr_tester.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,10 @@ class TimeEINTRTest(EINTRBaseTest):
258258

259259
def test_sleep(self):
260260
t0 = time.monotonic()
261-
# time.sleep() may retry when interrupted by a signal
262-
time.sleep(2)
261+
time.sleep(self.sleep_time)
263262
signal.alarm(0)
264263
dt = time.monotonic() - t0
265-
# Tolerate a difference 100 ms: on Windows, time.monotonic() has
266-
# a resolution of 15.6 ms or greater
267-
self.assertGreaterEqual(dt, 1.9)
264+
self.assertGreaterEqual(dt, self.sleep_time)
268265

269266

270267
def test_main():

Modules/socketmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ internal_select(PySocketSockObject *s, int writing)
687687
if (has_timeout) { \
688688
_PyTime_monotonic(&now); \
689689
deadline = now; \
690-
_PyTime_ADD_SECONDS(deadline, s->sock_timeout); \
690+
_PyTime_AddDouble(&deadline, s->sock_timeout, _PyTime_ROUND_UP); \
691691
} \
692692
while (1) { \
693693
errno = 0; \

Modules/timemodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,14 +1399,14 @@ floatsleep(double secs)
13991399
#endif
14001400

14011401
_PyTime_monotonic(&deadline);
1402-
_PyTime_ADD_SECONDS(deadline, secs);
1402+
_PyTime_AddDouble(&deadline, secs, _PyTime_ROUND_UP);
14031403

14041404
do {
14051405
#ifndef MS_WINDOWS
14061406
frac = fmod(secs, 1.0);
14071407
secs = floor(secs);
14081408
timeout.tv_sec = (long)secs;
1409-
timeout.tv_usec = (long)(frac*1000000.0);
1409+
timeout.tv_usec = (long)(frac*1e6);
14101410

14111411
Py_BEGIN_ALLOW_THREADS
14121412
err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);

Python/pytime.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,23 @@ _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
367367
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
368368
}
369369

370+
void
371+
_PyTime_AddDouble(_PyTime_timeval *tv, double interval, _PyTime_round_t round)
372+
{
373+
_PyTime_timeval tv2;
374+
double frac;
375+
376+
frac = fmod(interval, 1.0);
377+
interval = floor(interval);
378+
tv2.tv_sec = (long)interval;
379+
tv2.tv_usec = (long)(frac*1e6);
380+
381+
tv->tv_sec += tv2.tv_sec;
382+
tv->tv_usec += tv2.tv_usec;
383+
tv->tv_sec += (time_t)(tv->tv_usec / 1000000);
384+
tv->tv_usec %= 1000000;
385+
}
386+
370387
int
371388
_PyTime_Init(void)
372389
{

0 commit comments

Comments
 (0)