Skip to content

gh-143650: Fix importlib race condition on import failure - #143651

Merged
encukou merged 5 commits into
python:mainfrom
gpshead:fix-import-race-condition
Feb 10, 2026
Merged

gh-143650: Fix importlib race condition on import failure#143651
encukou merged 5 commits into
python:mainfrom
gpshead:fix-import-race-condition

Conversation

@gpshead

@gpsheadgpshead commented Jan 10, 2026

Copy link
Copy Markdown
Member

Fix race condition where a thread could receive a stale module reference when another thread's import fails. Adds verification after the "skip lock" fast path in both Python and C code paths to check if the module is still in sys.modules before returning it.

Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
Changes:
- Lib/importlib/_bootstrap.py: Add check after fast path in _find_and_load()
- Python/import.c: Add checks in PyImport_GetModule() and
PyImport_ImportModuleLevelObject()
- Add regression test test_import_failure_race_condition()
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gpshead
gpsheadforce-pushed the fix-import-race-condition branch from 78fed07 to 6393e97CompareJanuary 10, 2026 11:10
Comment threadPython/import.c
@gpsheadgpshead added needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes 🔨 test-with-buildbots Test PR w/ buildbots; report in status section labels Jan 10, 2026
@bedevere-bot

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @gpshead for commit 0a682cd 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F143651%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-botbedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jan 10, 2026
Add error checking inside the `if (mod_check != mod)` block to properly
handle the case where import_get_module itself fails with an exception.
Also refactor PyImport_GetModule to use an error label for cleanup.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gpshead
gpsheadforce-pushed the fix-import-race-condition branch from 45c02dc to 842c160CompareJanuary 10, 2026 21:14
@gpshead

Copy link
Copy Markdown
MemberAuthor

the few buildbot failures in the earlier round all looked like network issues. not rerunning those.

@gpshead
gpshead requested review from picnixz and pitrouJanuary 11, 2026 18:24
Comment threadPython/import.c Outdated
@gpsheadgpshead added 🔨 test-with-buildbots Test PR w/ buildbots; report in status section 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section labels Jan 11, 2026
@bedevere-bot

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @gpshead for commit 102845b 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F143651%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @gpshead for commit 102845b 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F143651%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

@bedevere-botbedevere-bot removed 🔨 test-with-buildbots Test PR w/ buildbots; report in status section 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section labels Jan 11, 2026
@gpshead
gpshead requested a review from picnixzJanuary 12, 2026 07:48
@encukouencukou added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Feb 4, 2026
@bedevere-bot

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @encukou for commit 179d7bf 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F143651%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-botbedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Feb 4, 2026
@encukou
encukou merged commit ac8b5b6 into python:mainFeb 10, 2026
118 of 120 checks passed
@miss-islington-app

Copy link
Copy Markdown

Thanks @gpshead for the PR, and @encukou for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Feb 10, 2026
…onGH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
(cherry picked from commit ac8b5b6)
Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@miss-islington-app

Copy link
Copy Markdown

Sorry, @gpshead and @encukou, I could not cleanly backport this to 3.13 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker ac8b5b6890006ee7254ea878866cb486ff835ecb 3.13

@bedevere-app

Copy link
Copy Markdown

GH-144662 is a backport of this pull request to the 3.14 branch.

@bedevere-appbedevere-appBot removed the needs backport to 3.14 bugs and security fixes label Feb 10, 2026
gpshead added a commit that referenced this pull request Feb 11, 2026
…143651) (#144662)
gh-143650: Fix importlib race condition on import failure (GH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
(cherry picked from commit ac8b5b6)
Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
gpshead added a commit to gpshead/cpython that referenced this pull request Feb 11, 2026
…onGH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
cherry picked from ac8b5b6
@bedevere-app

Copy link
Copy Markdown

GH-144697 is a backport of this pull request to the 3.13 branch.

@bedevere-appbedevere-appBot removed the needs backport to 3.13 bugs and security fixes label Feb 11, 2026
gpshead added a commit that referenced this pull request Feb 11, 2026
…143651) (#144697)
gh-143650: Fix importlib race condition on import failure (GH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
cherry picked from ac8b5b6
thunder-coding pushed a commit to thunder-coding/cpython that referenced this pull request Feb 15, 2026
…onGH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
brijkapadia pushed a commit to brijkapadia/cpython that referenced this pull request Feb 28, 2026
…onGH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ljfp pushed a commit to ljfp/cpython that referenced this pull request Apr 25, 2026
…onGH-143651)
Fix a race condition where a thread could receive a partially-initialized
module when another thread's import fails. The race occurs when:
1. Thread 1 starts importing, adds module to sys.modules
2. Thread 2 sees the module in sys.modules via the fast path
3. Thread 1's import fails, removes module from sys.modules
4. Thread 2 returns a stale module reference not in sys.modules
The fix adds verification after the "skip lock" optimization in both Python
and C code paths to check if the module is still in sys.modules. If the
module was removed (due to import failure), we retry the import so the
caller receives the actual exception from the import failure rather than
a stale module reference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@gpshead@bedevere-bot@picnixz@encukou