Skip to content

Evidence for #1833: sandbox importer module-lock race fails on main (Python 3.10) - #1888

Draft
DABH wants to merge 1 commit into
mainfrom
evidence/sandbox-importer-lock-race
Draft

DABH wants to merge 1 commit into
mainfrom
evidence/sandbox-importer-lock-race

Conversation

@DABH

@DABH DABH commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Draft, not for merge — evidence for #1833 (the Failed validating workflow / KeyError: <thread id> flake, tracked as #585 since July 2024).

Two tests against main's sandbox importer. Both fail on every Python 3.10 lane here and pass on #1833; both skip on 3.12+, where CPython fixed its side of the bug:

  • test_workflow_sandbox_importer_loaded_module_import_inside_module_lock — the regression test from Skip importlib for already-loaded modules in the workflow sandbox #1833, standalone. Rebuilds _ModuleLock.acquire from the interpreter's own _bootstrap.py with an import of the already-loaded warnings module placed inside the _blocking_on[tid] window, which is what a GC finalizer's RuntimeWarning does mid-import. Fails with the CI signature: _importer.py → importlib.__import__ → _find_and_load → _ModuleLockManager.__enter__ → acquire → KeyError(<tid>).
  • test_workflow_sandbox_importer_survives_gc_finalizer_imports — the same failure with no CPython internals touched: a garbage cycle whose finalizer imports the already-loaded warnings module is kept perpetually pending, and gc.set_threshold(1) runs the collector at nearly every allocation. On main under 3.10 every sandboxed import of asyncio raises KeyError (3/3 in CI on all six 3.10 lanes, 300/300 locally); on Skip importlib for already-loaded modules in the workflow sandbox #1833, 0.

Why 3.10 only: CPython's C __import__ returns a module already in sys.modules without touching a module lock, and since 3.12 the pure-Python importlib._find_and_load does too ("Optimization: we avoid unneeded module locking if the module already exists in sys.modules and is fully initialized"), with acquire made re-entrant in python/cpython#91351. The sandbox routes every import through pure-Python importlib.__import__, which on 3.10/3.11 acquires the module lock before checking sys.modules, so every sandboxed import of an already-loaded module opens the window the bug lives in. #1833 does for the sandbox what 3.12 does natively: serve fully-loaded modules straight from sys.modules and leave first-time loads (and fromlist / relative forms) on importlib.

Local runs (_importer.py swapped between main and #1833, same test file):

main  importer, Python 3.10.20: 2 failed   KeyError: 8482349440 / 300/300 imports raised KeyError inside importlib
#1833 importer, Python 3.10.20: 2 passed
main  importer, Python 3.14.3:  natural test run unskipped → 0/2000 KeyErrors (CPython's fix); both tests skip in CI

@DABH
DABH force-pushed the evidence/sandbox-importer-lock-race branch 2 times, most recently from 782ae7f to 84532f3 Compare September 20, 2026 06:33
@DABH DABH added the skip-changelog PR changes do not require changelog updates label Sep 20, 2026
@DABH
DABH force-pushed the evidence/sandbox-importer-lock-race branch from 84532f3 to 4bc0a5a Compare September 20, 2026 06:34
Evidence for #1833. Both tests fail on main under Python 3.10 with the
KeyError(<thread id>) from importlib._bootstrap._ModuleLock.acquire behind
the 'Failed validating workflow' flake (#585), and pass with #1833. The
natural variant patches no CPython internals and passes on 3.12+, where
python/cpython#91351 is fixed.
@DABH
DABH force-pushed the evidence/sandbox-importer-lock-race branch from 4bc0a5a to cfaefda Compare September 20, 2026 07:00

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog PR changes do not require changelog updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant