|
|
956e31 |
diff --git a/Lib/threading.py b/Lib/threading.py
|
|
|
956e31 |
index 7ab9ad8..dcedd3b 100644
|
|
|
956e31 |
--- a/Lib/threading.py
|
|
|
956e31 |
+++ b/Lib/threading.py
|
|
|
956e31 |
@@ -3,7 +3,7 @@
|
|
|
956e31 |
import sys as _sys
|
|
|
956e31 |
import _thread
|
|
|
956e31 |
|
|
|
956e31 |
-from time import monotonic as _time
|
|
|
956e31 |
+from time import monotonic as _time, sleep as _sleep
|
|
|
956e31 |
from traceback import format_exc as _format_exc
|
|
|
956e31 |
from _weakrefset import WeakSet
|
|
|
956e31 |
from itertools import islice as _islice, count as _count
|
|
|
956e31 |
@@ -296,7 +296,25 @@ class Condition:
|
|
|
956e31 |
gotit = True
|
|
|
956e31 |
else:
|
|
|
956e31 |
if timeout > 0:
|
|
|
956e31 |
- gotit = waiter.acquire(True, timeout)
|
|
|
956e31 |
+ # rhbz#2003758: Avoid waiter.acquire(True, timeout) since
|
|
|
956e31 |
+ # it uses the system clock internally.
|
|
|
956e31 |
+ #
|
|
|
956e31 |
+ # Balancing act: We can't afford a pure busy loop, so we
|
|
|
956e31 |
+ # have to sleep; but if we sleep the whole timeout time,
|
|
|
956e31 |
+ # we'll be unresponsive. The scheme here sleeps very
|
|
|
956e31 |
+ # little at first, longer as time goes on, but never longer
|
|
|
956e31 |
+ # than 20 times per second (or the timeout time remaining).
|
|
|
956e31 |
+ endtime = _time() + timeout
|
|
|
956e31 |
+ delay = 0.0005 # 500 us -> initial delay of 1 ms
|
|
|
956e31 |
+ while True:
|
|
|
956e31 |
+ gotit = waiter.acquire(0)
|
|
|
956e31 |
+ if gotit:
|
|
|
956e31 |
+ break
|
|
|
956e31 |
+ remaining = min(endtime - _time(), timeout)
|
|
|
956e31 |
+ if remaining <= 0:
|
|
|
956e31 |
+ break
|
|
|
956e31 |
+ delay = min(delay * 2, remaining, .05)
|
|
|
956e31 |
+ _sleep(delay)
|
|
|
956e31 |
else:
|
|
|
956e31 |
gotit = waiter.acquire(False)
|
|
|
956e31 |
return gotit
|