mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 13:11:29 +00:00 
			
		
		
		
	gh-117300: Use stop the world to make sys._current_frames and sys._current_exceptions thread-safe. (#117301)
				
					
				
			This adds a stop the world pause to make the two functions thread-safe when the GIL is disabled in the free-threaded build. Additionally, the main test thread may call `sys._current_exceptions()` as soon as `g_raised.set()` is called. The background thread may not yet reach the `leave_g.wait()` line.
This commit is contained in:
		
							parent
							
								
									94c97423a9
								
							
						
					
					
						commit
						01bd74eadb
					
				
					 2 changed files with 6 additions and 1 deletions
				
			
		|  | @ -562,7 +562,8 @@ def g456(): | ||||||
|             # And the next record must be for g456(). |             # And the next record must be for g456(). | ||||||
|             filename, lineno, funcname, sourceline = stack[i+1] |             filename, lineno, funcname, sourceline = stack[i+1] | ||||||
|             self.assertEqual(funcname, "g456") |             self.assertEqual(funcname, "g456") | ||||||
|             self.assertTrue(sourceline.startswith("if leave_g.wait(")) |             self.assertTrue((sourceline.startswith("if leave_g.wait(") or | ||||||
|  |                              sourceline.startswith("g_raised.set()"))) | ||||||
|         finally: |         finally: | ||||||
|             # Reap the spawned thread. |             # Reap the spawned thread. | ||||||
|             leave_g.set() |             leave_g.set() | ||||||
|  |  | ||||||
|  | @ -2408,6 +2408,7 @@ _PyThread_CurrentFrames(void) | ||||||
|      * Because these lists can mutate even when the GIL is held, we |      * Because these lists can mutate even when the GIL is held, we | ||||||
|      * need to grab head_mutex for the duration. |      * need to grab head_mutex for the duration. | ||||||
|      */ |      */ | ||||||
|  |     _PyEval_StopTheWorldAll(runtime); | ||||||
|     HEAD_LOCK(runtime); |     HEAD_LOCK(runtime); | ||||||
|     PyInterpreterState *i; |     PyInterpreterState *i; | ||||||
|     for (i = runtime->interpreters.head; i != NULL; i = i->next) { |     for (i = runtime->interpreters.head; i != NULL; i = i->next) { | ||||||
|  | @ -2441,6 +2442,7 @@ _PyThread_CurrentFrames(void) | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|     HEAD_UNLOCK(runtime); |     HEAD_UNLOCK(runtime); | ||||||
|  |     _PyEval_StartTheWorldAll(runtime); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2472,6 +2474,7 @@ _PyThread_CurrentExceptions(void) | ||||||
|      * Because these lists can mutate even when the GIL is held, we |      * Because these lists can mutate even when the GIL is held, we | ||||||
|      * need to grab head_mutex for the duration. |      * need to grab head_mutex for the duration. | ||||||
|      */ |      */ | ||||||
|  |     _PyEval_StopTheWorldAll(runtime); | ||||||
|     HEAD_LOCK(runtime); |     HEAD_LOCK(runtime); | ||||||
|     PyInterpreterState *i; |     PyInterpreterState *i; | ||||||
|     for (i = runtime->interpreters.head; i != NULL; i = i->next) { |     for (i = runtime->interpreters.head; i != NULL; i = i->next) { | ||||||
|  | @ -2504,6 +2507,7 @@ _PyThread_CurrentExceptions(void) | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|     HEAD_UNLOCK(runtime); |     HEAD_UNLOCK(runtime); | ||||||
|  |     _PyEval_StartTheWorldAll(runtime); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Gross
						Sam Gross