[Python-checkins] bpo-34819: Use a monotonic clock to compute timeouts in concurrent.futures (GH-9599)

Miss Islington (bot) webhook-mailer at python.org
Thu Sep 27 07:37:37 EDT 2018


https://github.com/python/cpython/commit/3a4aa6ac55e04c42757443d5b5854b6d893e0461
commit: 3a4aa6ac55e04c42757443d5b5854b6d893e0461
branch: 3.6
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2018-09-27T04:37:33-07:00
summary:

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 <orlnub123 at gmail.com>

files:
A Misc/NEWS.d/next/Library/2018-09-27-09-45-00.bpo-34819.9ZaFyO.rst
M Lib/concurrent/futures/_base.py

diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py
index 6bace6c74641..4c140508c9ea 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 @@ def map(self, fn, *iterables, timeout=None, chunksize=1):
             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 @@ def result_iterator():
                     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.



More information about the Python-checkins mailing list