mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-130094: Fix race conditions in importlib (gh-130101)
				
					
				
			Entries may be added or removed from `sys.meta_path` concurrently. For example, setuptools temporarily adds and removes the `distutils` finder from the beginning of the list. The local copy ensures that we don't skip over any entries. Some packages modify `sys.modules` during import. For example, `collections` inserts the entry for `collections.abc` into `sys.modules` during import. We need to ensure that we re-check `sys.modules` *after* the parent module is fully initialized.
This commit is contained in:
		
							parent
							
								
									8207454bc0
								
							
						
					
					
						commit
						857bdba0ac
					
				
					 2 changed files with 14 additions and 3 deletions
				
			
		|  | @ -1244,6 +1244,9 @@ def _find_spec(name, path, target=None): | ||||||
|         raise ImportError("sys.meta_path is None, Python is likely " |         raise ImportError("sys.meta_path is None, Python is likely " | ||||||
|                           "shutting down") |                           "shutting down") | ||||||
| 
 | 
 | ||||||
|  |     # gh-130094: Copy sys.meta_path so that we have a consistent view of the | ||||||
|  |     # list while iterating over it. | ||||||
|  |     meta_path = list(meta_path) | ||||||
|     if not meta_path: |     if not meta_path: | ||||||
|         _warnings.warn('sys.meta_path is empty', ImportWarning) |         _warnings.warn('sys.meta_path is empty', ImportWarning) | ||||||
| 
 | 
 | ||||||
|  | @ -1298,7 +1301,6 @@ def _sanity_check(name, package, level): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| _ERR_MSG_PREFIX = 'No module named ' | _ERR_MSG_PREFIX = 'No module named ' | ||||||
| _ERR_MSG = _ERR_MSG_PREFIX + '{!r}' |  | ||||||
| 
 | 
 | ||||||
| def _find_and_load_unlocked(name, import_): | def _find_and_load_unlocked(name, import_): | ||||||
|     path = None |     path = None | ||||||
|  | @ -1308,8 +1310,9 @@ def _find_and_load_unlocked(name, import_): | ||||||
|         if parent not in sys.modules: |         if parent not in sys.modules: | ||||||
|             _call_with_frames_removed(import_, parent) |             _call_with_frames_removed(import_, parent) | ||||||
|         # Crazy side-effects! |         # Crazy side-effects! | ||||||
|         if name in sys.modules: |         module = sys.modules.get(name) | ||||||
|             return sys.modules[name] |         if module is not None: | ||||||
|  |             return module | ||||||
|         parent_module = sys.modules[parent] |         parent_module = sys.modules[parent] | ||||||
|         try: |         try: | ||||||
|             path = parent_module.__path__ |             path = parent_module.__path__ | ||||||
|  | @ -1317,6 +1320,12 @@ def _find_and_load_unlocked(name, import_): | ||||||
|             msg = f'{_ERR_MSG_PREFIX}{name!r}; {parent!r} is not a package' |             msg = f'{_ERR_MSG_PREFIX}{name!r}; {parent!r} is not a package' | ||||||
|             raise ModuleNotFoundError(msg, name=name) from None |             raise ModuleNotFoundError(msg, name=name) from None | ||||||
|         parent_spec = parent_module.__spec__ |         parent_spec = parent_module.__spec__ | ||||||
|  |         if getattr(parent_spec, '_initializing', False): | ||||||
|  |             _call_with_frames_removed(import_, parent) | ||||||
|  |         # Crazy side-effects (again)! | ||||||
|  |         module = sys.modules.get(name) | ||||||
|  |         if module is not None: | ||||||
|  |             return module | ||||||
|         child = name.rpartition('.')[2] |         child = name.rpartition('.')[2] | ||||||
|     spec = _find_spec(name, path) |     spec = _find_spec(name, path) | ||||||
|     if spec is None: |     if spec is None: | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | Fix two race conditions involving concurrent imports that could lead to | ||||||
|  | spurious failures with :exc:`ModuleNotFoundError`. | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Gross
						Sam Gross