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