mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-96387: take_gil() resets drop request before exit (#96869)
At Python exit, sometimes a thread holding the GIL can wait forever for a thread (usually a daemon thread) which requested to drop the GIL, whereas the thread already exited. To fix the race condition, the thread which requested the GIL drop now resets its request before exiting. take_gil() now calls RESET_GIL_DROP_REQUEST() before PyThread_exit_thread() if it called SET_GIL_DROP_REQUEST to fix a race condition with drop_gil(). Issue discovered and analyzed by Mingliang ZHAO.
This commit is contained in:
		
							parent
							
								
									c10e33ac11
								
							
						
					
					
						commit
						04f4977f50
					
				
					 2 changed files with 16 additions and 0 deletions
				
			
		|  | @ -369,6 +369,7 @@ take_gil(PyThreadState *tstate) | |||
|         goto _ready; | ||||
|     } | ||||
| 
 | ||||
|     int drop_requested = 0; | ||||
|     while (_Py_atomic_load_relaxed(&gil->locked)) { | ||||
|         unsigned long saved_switchnum = gil->switch_number; | ||||
| 
 | ||||
|  | @ -384,11 +385,21 @@ take_gil(PyThreadState *tstate) | |||
|         { | ||||
|             if (tstate_must_exit(tstate)) { | ||||
|                 MUTEX_UNLOCK(gil->mutex); | ||||
|                 // gh-96387: If the loop requested a drop request in a previous
 | ||||
|                 // iteration, reset the request. Otherwise, drop_gil() can
 | ||||
|                 // block forever waiting for the thread which exited. Drop
 | ||||
|                 // requests made by other threads are also reset: these threads
 | ||||
|                 // may have to request again a drop request (iterate one more
 | ||||
|                 // time).
 | ||||
|                 if (drop_requested) { | ||||
|                     RESET_GIL_DROP_REQUEST(interp); | ||||
|                 } | ||||
|                 PyThread_exit_thread(); | ||||
|             } | ||||
|             assert(is_tstate_valid(tstate)); | ||||
| 
 | ||||
|             SET_GIL_DROP_REQUEST(interp); | ||||
|             drop_requested = 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner