Skip to content

Fix: tolerate a concurrent removal of a dead symlink at session finish - #15174

Open
zyv wants to merge 1 commit into
pytest-dev:mainfrom
zyv:feature/fix-symlink-cleanup-race
Open

zyv wants to merge 1 commit into
pytest-dev:mainfrom
zyv:feature/fix-symlink-cleanup-race

Conversation

@zyv

@zyv zyv commented Oct 13, 2026

Copy link
Copy Markdown

I run many pytest sessions in parallel (mutmut forks a worker per CPU, and each worker runs pytest.main). Now and then a session fails at session finish:

  File ".../_pytest/pathlib.py", line 371, in cleanup_numbered_dir
    cleanup_dead_symlinks(root)
  File ".../_pytest/pathlib.py", line 357, in cleanup_dead_symlinks
    left_dir.unlink()
FileNotFoundError: [Errno 2] No such file or directory: '.../pytest-of-<user>/pytest-current'

cleanup_dead_symlinks checks that a link is dead, then unlinks it, and another session can unlink the same link in-between. This reproduces for me on macOS with pytest 9.1.1 (it takes a few rounds):

printf 'def test(tmp_path):\n    pass\n' > test_a.py
export PYTEST_DEBUG_TEMPROOT=$(mktemp -d)
for round in $(seq 10); do
  for i in $(seq 32); do
    python -m pytest -q -p no:cacheprovider -o tmp_path_retention_count=1 test_a.py > out.$i 2>&1 &
  done
  wait
  grep -l FileNotFoundError out.*
done

The fix passes missing_ok=True to unlink.

I haven't found any already reported issues to that effect.

The problem was identified using a supervised agent, and I have reviewed the code and the test - mutmut does no longer attribute flaky mutant kills to pytest session crashes.

Concurrent sessions of one user share `pytest-of-<user>`, and a session can
unlink the dead `pytest-current` symlink after another session checked it,
which raised `FileNotFoundError` from `pytest_sessionfinish`.

Co-authored-by: Claude Opus 5.5
Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
@zyv
zyv force-pushed the feature/fix-symlink-cleanup-race branch from 5e145bf to 10b1643 Compare October 14, 2026 08:06
@zyv zyv changed the title Tolerate a concurrent removal of a dead symlink at session finish Fix: tolerate a concurrent removal of a dead symlink at session finish Oct 14, 2026
@zyv

zyv commented Oct 14, 2026

Copy link
Copy Markdown
Author

I have added the changelog entry under this PR's number, and the last edit is cosmetic - it hopefully removes 1 uncovered line in the mock. I'm not sure what was up with readthedocs; I guess it was some problem unrelated to my changes, but everything seems to be green now.

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

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant