https://github.com/python/cpython/commit/b0a181d8fcf691f4d9eaabc6d39de1eefc863272
commit: b0a181d8fcf691f4d9eaabc6d39de1eefc863272
branch: 3.13
author: Daehee Kim <[email protected]>
committer: corona10 <[email protected]>
date: 2026-08-17T11:53:32+09:00
summary:

[3.13] gh-130094: Fix race conditions in `importlib` (gh-130101) (gh-155915)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-02-14-00-32-52.gh-issue-130094.m3EF9E.rst
M Lib/importlib/_bootstrap.py

diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index aed993cc6b16ab4..daec82c99242b2f 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -1245,6 +1245,9 @@ def _find_spec(name, path, target=None):
         raise ImportError("sys.meta_path is None, Python is likely "
                           "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:
         _warnings.warn('sys.meta_path is empty', ImportWarning)
 
@@ -1299,7 +1302,6 @@ def _sanity_check(name, package, level):
 
 
 _ERR_MSG_PREFIX = 'No module named '
-_ERR_MSG = _ERR_MSG_PREFIX + '{!r}'
 
 def _find_and_load_unlocked(name, import_):
     path = None
@@ -1309,8 +1311,9 @@ def _find_and_load_unlocked(name, import_):
         if parent not in sys.modules:
             _call_with_frames_removed(import_, parent)
         # Crazy side-effects!
-        if name in sys.modules:
-            return sys.modules[name]
+        module = sys.modules.get(name)
+        if module is not None:
+            return module
         parent_module = sys.modules[parent]
         try:
             path = parent_module.__path__
@@ -1318,6 +1321,12 @@ def _find_and_load_unlocked(name, import_):
             msg = f'{_ERR_MSG_PREFIX}{name!r}; {parent!r} is not a package'
             raise ModuleNotFoundError(msg, name=name) from None
         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]
     spec = _find_spec(name, path)
     if spec is None:
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-14-00-32-52.gh-issue-130094.m3EF9E.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-14-00-32-52.gh-issue-130094.m3EF9E.rst
new file mode 100644
index 000000000000000..15d5831808df638
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-14-00-32-52.gh-issue-130094.m3EF9E.rst
@@ -0,0 +1,2 @@
+Fix two race conditions involving concurrent imports that could lead to
+spurious failures with :exc:`ModuleNotFoundError`.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to