🐛 fix(soft): skip stale lock detection on Windows#477
Merged
gaborbernat merged 1 commit intotox-dev:mainfrom Feb 14, 2026
Merged
🐛 fix(soft): skip stale lock detection on Windows#477gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat merged 1 commit intotox-dev:mainfrom
Conversation
Python's _wopen() cannot set FILE_SHARE_DELETE, so any read handle on the lock file blocks DeleteFileW in _release, causing a livelock under threaded contention. On Windows EACCES already signals the holder is alive (fd still open) and EEXIST means the releasing thread will clean up shortly, so stale detection adds no value there. Removes the CreateFileW/FILE_SHARE_DELETE read path and the mtime-based threshold, both of which were insufficient. Stale detection now runs only on Unix/macOS where unlink succeeds regardless of open handles.
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.
The stale lock detection merged in #476 causes livelock on Windows under threaded contention. Python's C runtime (
_wopen) cannot setFILE_SHARE_DELETE, so any read handle opened by_try_break_stale_lockblocksDeleteFileWin_release. With many threads competing, there is always at least one reader holding the lock file open, preventing deletion and orphaning the lock forever.This removes the
CreateFileW/FILE_SHARE_DELETEread path and the_STALE_LOCK_MIN_AGEmtime threshold — both were insufficient workarounds. Stale detection is now guarded withsys.platform != "win32"and only runs on Unix/macOS whereunlink()succeeds regardless of open handles. On Windows,EACCESalready signals the holder is alive (fd still open) andEEXISTresolves as the releasing thread deletes the file, so stale detection adds no value.Docs updated to note the Windows limitation. Tests for stale detection are now marked
@unix_only.Why stale detection is fundamentally broken on Windows
The issue comes down to how Windows file deletion works vs Unix:
DeleteFileWrequires all existing handles to the file to have been opened withFILE_SHARE_DELETE. If any handle lacks this flag, deletion fails withERROR_SHARING_VIOLATION.CreateFileWis the only Win32 API that allows settingFILE_SHARE_DELETEviadwShareMode.os.open()uses the MSVC CRT_wopenwhich callsCreateFileWinternally but does not exposeFILE_SHARE_DELETE— it only setsFILE_SHARE_READ | FILE_SHARE_WRITE.CreateFileWdirectly viactypeswithFILE_SHARE_DELETEfor the read handle is insufficient: the write handle (fromos.openin_acquire) also lacksFILE_SHARE_DELETE, soDeleteFileWstill fails while the holder has the file open.DeleteFileWsucceeds withFILE_SHARE_DELETE, it only marks the file for deletion — the file name remains visible in the directory until the last handle closes. Python'sos.unlink()uses standardDeleteFileW, notFileDispositionInfoExwithFILE_DISPOSITION_FLAG_POSIX_SEMANTICSwhich would provide immediate name removal.There is no
os.O_SHARE_DELETEflag in Python 3.10–3.14, and no open CPython proposal to add one.Considered alternative: sidecar info file
A sidecar file approach (
{lock_file}.info) would store PID/hostname separately so reading it doesn't block deletion of the lock file itself. This would work but was deemed not worth the complexity:.infofile may be missing (crash between lock creation and info write) or stale — requiring graceful fallbackSoftFileLockon Windows is a niche case — Windows normally usesWindowsFileLock(msvcrt) via theFileLockalias, so stale locks are primarily a Unix problem (CI systems, long-running daemons)This can be revisited if there is demand for Windows stale detection.