Skip to content

🐛 fix(api): resolve thread-safety races in build API#1015

Merged
gaborbernat merged 1 commit intopypa:mainfrom
gaborbernat:fix/thread-safety-issues
Apr 9, 2026
Merged

🐛 fix(api): resolve thread-safety races in build API#1015
gaborbernat merged 1 commit intopypa:mainfrom
gaborbernat:fix/thread-safety-issues

Conversation

@gaborbernat
Copy link
Copy Markdown
Collaborator

@gaborbernat gaborbernat commented Apr 9, 2026

An adversarial audit of thread-safety (per #377) found three remaining races after the os.chdir() removal in #536. While the core ProjectBuilder API works correctly with separate instances per thread, these edge cases can bite callers using shared output directories or concurrent environment teardown.

🔧 _call_backend uses os.path.exists() followed by os.makedirs() without exist_ok=True. Two threads building into the same output directory race on directory creation, and one crashes with FileExistsError. DefaultIsolatedEnv.__exit__ has a similar TOCTOU between os.path.exists() and shutil.rmtree(). The verbosity flag construction in both _PipBackend and _UvBackend reads _ctx.verbosity twice without caching, allowing an inconsistent value if the context changes between reads.

A separate subprocess_runner() context manager race lives upstream in pyproject_hooks — filed as pypa/pyproject-hooks#226.

Closes #377

- 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
@gaborbernat gaborbernat added the bug Something isn't working label Apr 9, 2026
@gaborbernat gaborbernat enabled auto-merge (squash) April 9, 2026 19:33
@gaborbernat gaborbernat merged commit f24bcd0 into pypa:main Apr 9, 2026
65 checks passed
gaborbernat added a commit to gaborbernat/build that referenced this pull request Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the API thread-safe

2 participants