mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Issue #14406: Fix a race condition when using concurrent.futures.wait(return_when=ALL_COMPLETED).
				
					
				
			Patch by Matt Joiner.
This commit is contained in:
		
						commit
						8b34b53c52
					
				
					 3 changed files with 25 additions and 4 deletions
				
			
		| 
						 | 
					@ -111,9 +111,11 @@ class _AllCompletedWaiter(_Waiter):
 | 
				
			||||||
    def __init__(self, num_pending_calls, stop_on_exception):
 | 
					    def __init__(self, num_pending_calls, stop_on_exception):
 | 
				
			||||||
        self.num_pending_calls = num_pending_calls
 | 
					        self.num_pending_calls = num_pending_calls
 | 
				
			||||||
        self.stop_on_exception = stop_on_exception
 | 
					        self.stop_on_exception = stop_on_exception
 | 
				
			||||||
 | 
					        self.lock = threading.Lock()
 | 
				
			||||||
        super().__init__()
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _decrement_pending_calls(self):
 | 
					    def _decrement_pending_calls(self):
 | 
				
			||||||
 | 
					        with self.lock:
 | 
				
			||||||
            self.num_pending_calls -= 1
 | 
					            self.num_pending_calls -= 1
 | 
				
			||||||
            if not self.num_pending_calls:
 | 
					            if not self.num_pending_calls:
 | 
				
			||||||
                self.event.set()
 | 
					                self.event.set()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -183,7 +183,9 @@ def test_del_shutdown(self):
 | 
				
			||||||
        for p in processes.values():
 | 
					        for p in processes.values():
 | 
				
			||||||
            p.join()
 | 
					            p.join()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class WaitTests(unittest.TestCase):
 | 
					class WaitTests(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_first_completed(self):
 | 
					    def test_first_completed(self):
 | 
				
			||||||
        future1 = self.executor.submit(mul, 21, 2)
 | 
					        future1 = self.executor.submit(mul, 21, 2)
 | 
				
			||||||
        future2 = self.executor.submit(time.sleep, 1.5)
 | 
					        future2 = self.executor.submit(time.sleep, 1.5)
 | 
				
			||||||
| 
						 | 
					@ -284,7 +286,21 @@ def test_timeout(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests):
 | 
					class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests):
 | 
				
			||||||
    pass
 | 
					
 | 
				
			||||||
 | 
					    def test_pending_calls_race(self):
 | 
				
			||||||
 | 
					        # Issue #14406: multi-threaded race condition when waiting on all
 | 
				
			||||||
 | 
					        # futures.
 | 
				
			||||||
 | 
					        event = threading.Event()
 | 
				
			||||||
 | 
					        def future_func():
 | 
				
			||||||
 | 
					            event.wait()
 | 
				
			||||||
 | 
					        oldswitchinterval = sys.getswitchinterval()
 | 
				
			||||||
 | 
					        sys.setswitchinterval(1e-6)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            fs = {self.executor.submit(future_func) for i in range(100)}
 | 
				
			||||||
 | 
					            event.set()
 | 
				
			||||||
 | 
					            futures.wait(fs, return_when=futures.ALL_COMPLETED)
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            sys.setswitchinterval(oldswitchinterval)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests):
 | 
					class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,9 @@ Core and Builtins
 | 
				
			||||||
Library
 | 
					Library
 | 
				
			||||||
-------
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Issue #14406: Fix a race condition when using ``concurrent.futures.wait(
 | 
				
			||||||
 | 
					  return_when=ALL_COMPLETED)``.  Patch by Matt Joiner.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Issue #5136: deprecate old, unused functions from tkinter.
 | 
					- Issue #5136: deprecate old, unused functions from tkinter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Issue #14409: IDLE now properly executes commands in the Shell window
 | 
					- Issue #14409: IDLE now properly executes commands in the Shell window
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue