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.

@zyv

zyv commented Oct 20, 2026

Copy link
Copy Markdown
Author

@RonnyPfannschmidt any chance you could have a look? Thank you!

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