Skip to content

Commit a94ee12

Browse files
orlnub123pitrou
authored andcommitted
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.
1 parent 7291108 commit a94ee12

File tree

2 files changed

+5
-4
lines changed

2 files changed

+5
-4
lines changed

Lib/concurrent/futures/_base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def as_completed(fs, timeout=None):
216216
before the given timeout.
217217
"""
218218
if timeout is not None:
219-
end_time = timeout + time.time()
219+
end_time = timeout + time.monotonic()
220220

221221
fs = set(fs)
222222
total_futures = len(fs)
@@ -235,7 +235,7 @@ def as_completed(fs, timeout=None):
235235
if timeout is None:
236236
wait_timeout = None
237237
else:
238-
wait_timeout = end_time - time.time()
238+
wait_timeout = end_time - time.monotonic()
239239
if wait_timeout < 0:
240240
raise TimeoutError(
241241
'%d (of %d) futures unfinished' % (
@@ -578,7 +578,7 @@ def map(self, fn, *iterables, timeout=None, chunksize=1):
578578
Exception: If fn(*args) raises for any values.
579579
"""
580580
if timeout is not None:
581-
end_time = timeout + time.time()
581+
end_time = timeout + time.monotonic()
582582

583583
fs = [self.submit(fn, *args) for args in zip(*iterables)]
584584

@@ -593,7 +593,7 @@ def result_iterator():
593593
if timeout is None:
594594
yield fs.pop().result()
595595
else:
596-
yield fs.pop().result(end_time - time.time())
596+
yield fs.pop().result(end_time - time.monotonic())
597597
finally:
598598
for future in fs:
599599
future.cancel()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

0 commit comments

Comments
 (0)