mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-135099: Only wait on _PyOS_SigintEvent() in main thread (GH-135100)
				
					
				
			On Windows, the `_PyOS_SigintEvent()` event handle is used to interrupt the main thread when Ctrl-C is pressed. Previously, we also waited on the event from other threads, but ignored the result. However, this can race with interpreter shutdown because the main thread closes the handle in `_PySignal_Fini` and threads may still be running and using mutexes during interpreter shtudown. Only use `_PyOS_SigintEvent()` in the main thread in parking_lot.c, like we do in other places in the CPython codebase.
This commit is contained in:
		
							parent
							
								
									8f778f7bb9
								
							
						
					
					
						commit
						cc581f32bf
					
				
					 2 changed files with 18 additions and 6 deletions
				
			
		|  | @ -0,0 +1,2 @@ | |||
| Fix a crash that could occur on Windows when a background thread waits on a | ||||
| :c:type:`PyMutex` while the main thread is shutting down the interpreter. | ||||
|  | @ -112,17 +112,27 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout) | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // NOTE: we wait on the sigint event even in non-main threads to match the
 | ||||
|     // behavior of the other platforms. Non-main threads will ignore the
 | ||||
|     // Py_PARK_INTR result.
 | ||||
|     HANDLE sigint_event = _PyOS_SigintEvent(); | ||||
|     HANDLE handles[2] = { sema->platform_sem, sigint_event }; | ||||
|     DWORD count = sigint_event != NULL ? 2 : 1; | ||||
|     HANDLE handles[2] = { sema->platform_sem, NULL }; | ||||
|     HANDLE sigint_event = NULL; | ||||
|     DWORD count = 1; | ||||
|     if (_Py_IsMainThread()) { | ||||
|         // gh-135099: Wait on the SIGINT event only in the main thread. Other
 | ||||
|         // threads would ignore the result anyways, and accessing
 | ||||
|         // `_PyOS_SigintEvent()` from non-main threads may race with
 | ||||
|         // interpreter shutdown, which closes the event handle. Note that
 | ||||
|         // non-main interpreters will ignore the result.
 | ||||
|         sigint_event = _PyOS_SigintEvent(); | ||||
|         if (sigint_event != NULL) { | ||||
|             handles[1] = sigint_event; | ||||
|             count = 2; | ||||
|         } | ||||
|     } | ||||
|     wait = WaitForMultipleObjects(count, handles, FALSE, millis); | ||||
|     if (wait == WAIT_OBJECT_0) { | ||||
|         res = Py_PARK_OK; | ||||
|     } | ||||
|     else if (wait == WAIT_OBJECT_0 + 1) { | ||||
|         assert(sigint_event != NULL); | ||||
|         ResetEvent(sigint_event); | ||||
|         res = Py_PARK_INTR; | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Gross
						Sam Gross