Skip to content

fix: clean up orphan build dirs from crashed runs#137

Draft
aiolibsbot wants to merge 3 commits into
bdraco:mainfrom
aiolibsbot:koan/cleanup-orphan-build-dirs
Draft

fix: clean up orphan build dirs from crashed runs#137
aiolibsbot wants to merge 3 commits into
bdraco:mainfrom
aiolibsbot:koan/cleanup-orphan-build-dirs

Conversation

@aiolibsbot
Copy link
Copy Markdown

@aiolibsbot aiolibsbot commented May 17, 2026

What

Sweep leftover `-tmpXXXX` directories (and `-build` symlinks) at the start of `make_index`, and stop the failure handler from masking the real exception.

Why

The atomic-replace flow in `_atomic_replace_old_index` does rename → symlink → replace. A crash between those steps leaves a fully-built `-tmpXXXX` directory in place forever — there is no GC anywhere. Worse, the existing `except` handler calls `rmtree(temp_dir)` on a path that was already renamed, raising `FileNotFoundError` and masking the original exception.

How

  • New `_cleanup_orphan_build_dirs` runs while the lock is held, before `mkdtemp`. It removes siblings matching the build-name prefix, while preserving the one the live symlink points at.
  • `rmtree(temp_dir, ignore_errors=True)` in the failure handler so the original traceback survives. Any orphan left behind is reclaimed by the next run's sweep.

Testing

  • New `test_make_index_fails_partial_replace` simulates a crash after the rename; asserts the real exception propagates and the orphan is cleaned on the next run.
  • New `test_make_index_cleans_orphan_build_symlink` seeds both an orphan dir and an orphan -build symlink; asserts both are gone after a successful run.
  • Full suite: 16 passed.

🤖 Generated with Claude Code


Quality Report

Changes: 2 files changed, 81 insertions(+), 2 deletions(-)

Code scan: clean

Tests: failed ([Errno 13] Permission denied: 'pytest')

Branch hygiene: 1 issue(s)

  • Branch is not pushed to remote

Generated by Kōan post-mission quality pipeline

aiolibsbot and others added 3 commits May 17, 2026 04:18
A crash between the rename and the final symlink-replace inside
_atomic_replace_old_index leaves <target>-tmpXXXX directories (and
sometimes -build symlinks) behind forever.

Two changes:
- Sweep matching siblings at startup while holding the lock; skip the
  one the live symlink points at.
- rmtree(temp_dir, ignore_errors=True) in the failure handler so a
  partial replace (where temp_dir was already renamed) no longer raises
  FileNotFoundError and masks the original exception.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to 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.

1 participant