Commit a94ee12c authored by orlnub123's avatar orlnub123 Committed by Antoine Pitrou

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.
parent 7291108d
...@@ -216,7 +216,7 @@ def as_completed(fs, timeout=None): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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()
......
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.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment