Skip to content

importlib race condition allows stale module ref to escape on failure #143650

Description

@gpshead

When a module import fails, other threads can receive a stale module reference that is no longer in sys.modules.

Race condition

  1. Thread 1 starts importing module X, adds it to sys.modules
  2. Thread 2 checks sys.modules, finds module X, takes the "skip lock" fast path
  3. Thread 1's import fails, removes module X from sys.modules
  4. Thread 2 returns the stale module reference (not in sys.modules)

Affected code paths

  • Lib/importlib/_bootstrap.py:_find_and_load() lines 1268-1282
  • Python/import.c:PyImport_GetModule()
  • Python/import.c:PyImport_ImportModuleLevelObject()

All three have an optimization that skips locking when a module appears already loaded, but none verify the module is still valid after checking _initializing.

Reproducer

importsysimportthreadingimporttempfileimportoswithtempfile.TemporaryDirectory() astmpdir:
sys.path.insert(0, tmpdir)
# Module that partially initializes then failswithopen(os.path.join(tmpdir, "failing_mod.py"), "w") asf:
f.write("import time; time.sleep(0.05); raise RuntimeError('fail')")
results= []
defdo_import(delay):
importtime; time.sleep(delay)
try:
mod=__import__("failing_mod")
if"failing_mod"notinsys.modules:
results.append("RACE: got module not in sys.modules")
exceptRuntimeError:
results.append("ok")
t1=threading.Thread(target=do_import, args=(0,))
t2=threading.Thread(target=do_import, args=(0.01,))
t1.start(); t2.start(); t1.join(); t2.join()
print(results) # May show "RACE" on affected builds

Linked PRs

Metadata

Metadata

Assignees

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)stdlibStandard Library Python modules in the Lib/ directorytopic-importlibtype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions