File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -111,12 +111,14 @@ class _AllCompletedWaiter(_Waiter):
111111 def __init__ (self , num_pending_calls , stop_on_exception ):
112112 self .num_pending_calls = num_pending_calls
113113 self .stop_on_exception = stop_on_exception
114+ self .lock = threading .Lock ()
114115 super ().__init__ ()
115116
116117 def _decrement_pending_calls (self ):
117- self .num_pending_calls -= 1
118- if not self .num_pending_calls :
119- self .event .set ()
118+ with self .lock :
119+ self .num_pending_calls -= 1
120+ if not self .num_pending_calls :
121+ self .event .set ()
120122
121123 def add_result (self , future ):
122124 super ().add_result (future )
Original file line number Diff line number Diff line change @@ -183,7 +183,9 @@ def test_del_shutdown(self):
183183 for p in processes .values ():
184184 p .join ()
185185
186+
186187class WaitTests (unittest .TestCase ):
188+
187189 def test_first_completed (self ):
188190 future1 = self .executor .submit (mul , 21 , 2 )
189191 future2 = self .executor .submit (time .sleep , 1.5 )
@@ -284,7 +286,21 @@ def test_timeout(self):
284286
285287
286288class ThreadPoolWaitTests (ThreadPoolMixin , WaitTests ):
287- pass
289+
290+ def test_pending_calls_race (self ):
291+ # Issue #14406: multi-threaded race condition when waiting on all
292+ # futures.
293+ event = threading .Event ()
294+ def future_func ():
295+ event .wait ()
296+ oldswitchinterval = sys .getswitchinterval ()
297+ sys .setswitchinterval (1e-6 )
298+ try :
299+ fs = {self .executor .submit (future_func ) for i in range (100 )}
300+ event .set ()
301+ futures .wait (fs , return_when = futures .ALL_COMPLETED )
302+ finally :
303+ sys .setswitchinterval (oldswitchinterval )
288304
289305
290306class ProcessPoolWaitTests (ProcessPoolMixin , WaitTests ):
Original file line number Diff line number Diff line change @@ -37,6 +37,9 @@ Core and Builtins
3737Library
3838-------
3939
40+ - Issue #14406: Fix a race condition when using ``concurrent.futures.wait(
41+ return_when=ALL_COMPLETED)``. Patch by Matt Joiner.
42+
4043- Issue #5136: deprecate old, unused functions from tkinter.
4144
4245- Issue #14409: IDLE now properly executes commands in the Shell window
You can’t perform that action at this time.
0 commit comments