mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	gh-116738: Make _codecs module thread-safe (#117530)
				
					
				
			The module itself is a thin wrapper around calls to functions in `Python/codecs.c`, so that's where the meaningful changes happened: - Move codecs-related state that lives on `PyInterpreterState` to a struct declared in `pycore_codecs.h`. - In free-threaded builds, add a mutex to `codecs_state` to synchronize operations on `search_path`. Because `search_path_mutex` is used as a normal mutex and not a critical section, we must be extremely careful with operations called while holding it. - The codec registry is explicitly initialized as part of `_PyUnicode_InitEncodings` to simplify thread-safety.
This commit is contained in:
		
							parent
							
								
									4e2caf2aa0
								
							
						
					
					
						commit
						f8290df63f
					
				
					 6 changed files with 120 additions and 79 deletions
				
			
		|  | @ -8,6 +8,17 @@ extern "C" { | |||
| #  error "this header requires Py_BUILD_CORE define" | ||||
| #endif | ||||
| 
 | ||||
| #include "pycore_lock.h"          // PyMutex | ||||
| 
 | ||||
| /* Initialize codecs-related state for the given interpreter, including
 | ||||
|    registering the first codec search function. Must be called before any other | ||||
|    PyCodec-related functions, and while only one thread is active. */ | ||||
| extern PyStatus _PyCodec_InitRegistry(PyInterpreterState *interp); | ||||
| 
 | ||||
| /* Finalize codecs-related state for the given interpreter. No PyCodec-related
 | ||||
|    functions other than PyCodec_Unregister() may be called after this. */ | ||||
| extern void _PyCodec_Fini(PyInterpreterState *interp); | ||||
| 
 | ||||
| extern PyObject* _PyCodec_Lookup(const char *encoding); | ||||
| 
 | ||||
| /* Text codec specific encoding and decoding API.
 | ||||
|  | @ -48,6 +59,26 @@ extern PyObject* _PyCodecInfo_GetIncrementalEncoder( | |||
|    PyObject *codec_info, | ||||
|    const char *errors); | ||||
| 
 | ||||
| // Per-interpreter state used by codecs.c.
 | ||||
| struct codecs_state { | ||||
|     // A list of callable objects used to search for codecs.
 | ||||
|     PyObject *search_path; | ||||
| 
 | ||||
|     // A dict mapping codec names to codecs returned from a callable in
 | ||||
|     // search_path.
 | ||||
|     PyObject *search_cache; | ||||
| 
 | ||||
|     // A dict mapping error handling strategies to functions to implement them.
 | ||||
|     PyObject *error_registry; | ||||
| 
 | ||||
| #ifdef Py_GIL_DISABLED | ||||
|     // Used to safely delete a specific item from search_path.
 | ||||
|     PyMutex search_path_mutex; | ||||
| #endif | ||||
| 
 | ||||
|     // Whether or not the rest of the state is initialized.
 | ||||
|     int initialized; | ||||
| }; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brett Simmers
						Brett Simmers