From 2b01121fd4200f1c27873422f7f72d02eec08630 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Thu, 27 Sep 2018 04:46:38 -0700 Subject: [PATCH] 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. (cherry picked from commit a94ee12c26aa8dd7dce01373779df8055aff765b) Co-authored-by: orlnub123 --- Lib/concurrent/futures/_base.py | 8 ++++---- .../next/Library/2018-09-27-09-45-00.bpo-34819.9ZaFyO.rst | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-09-27-09-45-00.bpo-34819.9ZaFyO.rst diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index 4f22f7ee0e6d..61c81bb7fe68 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -212,7 +212,7 @@ def as_completed(fs, timeout=None): before the given timeout. """ if timeout is not None: - end_time = timeout + time.time() + end_time = timeout + time.monotonic() fs = set(fs) total_futures = len(fs) @@ -231,7 +231,7 @@ def as_completed(fs, timeout=None): if timeout is None: wait_timeout = None else: - wait_timeout = end_time - time.time() + wait_timeout = end_time - time.monotonic() if wait_timeout < 0: raise TimeoutError( '%d (of %d) futures unfinished' % ( @@ -570,7 +570,7 @@ class Executor(object): Exception: If fn(*args) raises for any values. """ 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)] @@ -585,7 +585,7 @@ class Executor(object): if timeout is None: yield fs.pop().result() else: - yield fs.pop().result(end_time - time.time()) + yield fs.pop().result(end_time - time.monotonic()) finally: for future in fs: future.cancel() diff --git a/Misc/NEWS.d/next/Library/2018-09-27-09-45-00.bpo-34819.9ZaFyO.rst b/Misc/NEWS.d/next/Library/2018-09-27-09-45-00.bpo-34819.9ZaFyO.rst new file mode 100644 index 000000000000..6bbdea235f03 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-09-27-09-45-00.bpo-34819.9ZaFyO.rst @@ -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. -- 2.47.3