mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
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.
This commit is contained in:
parent
4fa99cdb4c
commit
9a8089b32a
5 changed files with 27 additions and 15 deletions
|
@ -41,13 +41,6 @@ PyAPI_FUNC(int) _PyTime_gettimeofday_info(
|
||||||
_PyTime_timeval *tp,
|
_PyTime_timeval *tp,
|
||||||
_Py_clock_info_t *info);
|
_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) \
|
#define _PyTime_INTERVAL(tv_start, tv_end) \
|
||||||
((tv_end.tv_sec - tv_start.tv_sec) + \
|
((tv_end.tv_sec - tv_start.tv_sec) + \
|
||||||
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
||||||
|
@ -109,6 +102,11 @@ PyAPI_FUNC(int) _PyTime_monotonic_info(
|
||||||
_PyTime_timeval *tp,
|
_PyTime_timeval *tp,
|
||||||
_Py_clock_info_t *info);
|
_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.
|
/* Initialize time.
|
||||||
Return 0 on success, raise an exception and return -1 on error. */
|
Return 0 on success, raise an exception and return -1 on error. */
|
||||||
PyAPI_FUNC(int) _PyTime_Init(void);
|
PyAPI_FUNC(int) _PyTime_Init(void);
|
||||||
|
|
|
@ -258,13 +258,10 @@ class TimeEINTRTest(EINTRBaseTest):
|
||||||
|
|
||||||
def test_sleep(self):
|
def test_sleep(self):
|
||||||
t0 = time.monotonic()
|
t0 = time.monotonic()
|
||||||
# time.sleep() may retry when interrupted by a signal
|
time.sleep(self.sleep_time)
|
||||||
time.sleep(2)
|
|
||||||
signal.alarm(0)
|
signal.alarm(0)
|
||||||
dt = time.monotonic() - t0
|
dt = time.monotonic() - t0
|
||||||
# Tolerate a difference 100 ms: on Windows, time.monotonic() has
|
self.assertGreaterEqual(dt, self.sleep_time)
|
||||||
# a resolution of 15.6 ms or greater
|
|
||||||
self.assertGreaterEqual(dt, 1.9)
|
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
|
|
|
@ -687,7 +687,7 @@ internal_select(PySocketSockObject *s, int writing)
|
||||||
if (has_timeout) { \
|
if (has_timeout) { \
|
||||||
_PyTime_monotonic(&now); \
|
_PyTime_monotonic(&now); \
|
||||||
deadline = now; \
|
deadline = now; \
|
||||||
_PyTime_ADD_SECONDS(deadline, s->sock_timeout); \
|
_PyTime_AddDouble(&deadline, s->sock_timeout, _PyTime_ROUND_UP); \
|
||||||
} \
|
} \
|
||||||
while (1) { \
|
while (1) { \
|
||||||
errno = 0; \
|
errno = 0; \
|
||||||
|
|
|
@ -1399,14 +1399,14 @@ floatsleep(double secs)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_PyTime_monotonic(&deadline);
|
_PyTime_monotonic(&deadline);
|
||||||
_PyTime_ADD_SECONDS(deadline, secs);
|
_PyTime_AddDouble(&deadline, secs, _PyTime_ROUND_UP);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
frac = fmod(secs, 1.0);
|
frac = fmod(secs, 1.0);
|
||||||
secs = floor(secs);
|
secs = floor(secs);
|
||||||
timeout.tv_sec = (long)secs;
|
timeout.tv_sec = (long)secs;
|
||||||
timeout.tv_usec = (long)(frac*1000000.0);
|
timeout.tv_usec = (long)(frac*1e6);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
|
err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
|
||||||
|
|
|
@ -367,6 +367,23 @@ _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
|
||||||
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
|
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
|
int
|
||||||
_PyTime_Init(void)
|
_PyTime_Init(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue