mirror of
https://github.com/python/cpython.git
synced 2025-11-26 21:33:10 +00:00
bpo-34819: Use a monotonic clock to compute timeouts in concurrent.futures (GH-9599)
Use a monotonic clock to compute timeouts in :meth:`Executor.map` and :func:`as_completed`, in order to prevent timeouts from deviating when the system clock is adjusted. This may not be sufficient on all systems. On POSIX for example, the actual waiting (e.g. in ``sem_timedwait``) is specified to rely on the CLOCK_REALTIME clock.
This commit is contained in:
parent
7291108d88
commit
a94ee12c26
2 changed files with 5 additions and 4 deletions
|
|
@ -216,7 +216,7 @@ def as_completed(fs, timeout=None):
|
||||||
before the given timeout.
|
before the given timeout.
|
||||||
"""
|
"""
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
end_time = timeout + time.time()
|
end_time = timeout + time.monotonic()
|
||||||
|
|
||||||
fs = set(fs)
|
fs = set(fs)
|
||||||
total_futures = len(fs)
|
total_futures = len(fs)
|
||||||
|
|
@ -235,7 +235,7 @@ def as_completed(fs, timeout=None):
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
wait_timeout = None
|
wait_timeout = None
|
||||||
else:
|
else:
|
||||||
wait_timeout = end_time - time.time()
|
wait_timeout = end_time - time.monotonic()
|
||||||
if wait_timeout < 0:
|
if wait_timeout < 0:
|
||||||
raise TimeoutError(
|
raise TimeoutError(
|
||||||
'%d (of %d) futures unfinished' % (
|
'%d (of %d) futures unfinished' % (
|
||||||
|
|
@ -578,7 +578,7 @@ class Executor(object):
|
||||||
Exception: If fn(*args) raises for any values.
|
Exception: If fn(*args) raises for any values.
|
||||||
"""
|
"""
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
end_time = timeout + time.time()
|
end_time = timeout + time.monotonic()
|
||||||
|
|
||||||
fs = [self.submit(fn, *args) for args in zip(*iterables)]
|
fs = [self.submit(fn, *args) for args in zip(*iterables)]
|
||||||
|
|
||||||
|
|
@ -593,7 +593,7 @@ class Executor(object):
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
yield fs.pop().result()
|
yield fs.pop().result()
|
||||||
else:
|
else:
|
||||||
yield fs.pop().result(end_time - time.time())
|
yield fs.pop().result(end_time - time.monotonic())
|
||||||
finally:
|
finally:
|
||||||
for future in fs:
|
for future in fs:
|
||||||
future.cancel()
|
future.cancel()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Use a monotonic clock to compute timeouts in :meth:`Executor.map` and :func:`as_completed`, in order to prevent timeouts from deviating when the system clock is adjusted.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue