🐛 fix(api): resolve thread-safety races in build API#1015
Merged
gaborbernat merged 1 commit intopypa:mainfrom Apr 9, 2026
Merged
🐛 fix(api): resolve thread-safety races in build API#1015gaborbernat merged 1 commit intopypa:mainfrom
gaborbernat merged 1 commit intopypa:mainfrom
Conversation
- Use exist_ok=True in os.makedirs to avoid TOCTOU race when multiple threads build to the same output directory - Cache _ctx.verbosity reads to prevent inconsistent double-read - Use shutil.rmtree(ignore_errors=True) instead of exists check to avoid TOCTOU in DefaultIsolatedEnv cleanup Ref: pypa#377 Upstream: pypa/pyproject-hooks#226
henryiii
approved these changes
Apr 9, 2026
gaborbernat
added a commit
to gaborbernat/build
that referenced
this pull request
Apr 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An adversarial audit of thread-safety (per #377) found three remaining races after the
os.chdir()removal in #536. While the coreProjectBuilderAPI works correctly with separate instances per thread, these edge cases can bite callers using shared output directories or concurrent environment teardown.🔧
_call_backendusesos.path.exists()followed byos.makedirs()withoutexist_ok=True. Two threads building into the same output directory race on directory creation, and one crashes withFileExistsError.DefaultIsolatedEnv.__exit__has a similar TOCTOU betweenos.path.exists()andshutil.rmtree(). The verbosity flag construction in both_PipBackendand_UvBackendreads_ctx.verbositytwice without caching, allowing an inconsistent value if the context changes between reads.A separate
subprocess_runner()context manager race lives upstream inpyproject_hooks— filed as pypa/pyproject-hooks#226.Closes #377