Skip to content

Dev/fix deadlock - #12

Merged
buzzer-re merged 4 commits into
mainfrom
dev/fix-deadlock
Jul 23, 2026
Merged

Dev/fix deadlock#12
buzzer-re merged 4 commits into
mainfrom
dev/fix-deadlock

Conversation

@buzzer-re

Copy link
Copy Markdown
Owner

Fix deadlock, closes #11

buzzer-re and others added 4 commits July 23, 2026 07:32
On Windows, write_text_atomic's tmp.replace(dst) fails with
PermissionError WinError 5 (access denied) or 32 (sharing violation) when
antivirus, the search indexer, or OneDrive briefly holds the destination or
temp file open without FILE_SHARE_DELETE. Under -j 8 the checkpoint is
rewritten on every completed function, so such a collision eventually aborts
the whole export (issue #11).

Wrap the replace in a bounded retry that backs off and retries only on those
transient winerror codes, then re-raises; other platforms and non-transient
errors are unaffected (winerror is None off Windows). On final failure the
temp file is removed so failures no longer leave .tmp orphans behind.

tests/test_atomic_write.py reproduces the exact failure with a real Windows
file lock (ctypes CreateFileW, read-share/no delete-share) and covers the
transient-recovers, permanent-still-raises, and no-retry-off-Windows cases,
plus a portable monkeypatched regression that runs on any platform.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes the "Command: ..." status log emitted at the start of a standard
export; the invocation is already discoverable and the line added noise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two pre-existing Windows portability issues broke the local CI gate on
Windows (both pass on the Linux CI, so they were latent):

- parallel.py: os.sysconf is POSIX-only, so mypy on Windows flagged the
  attribute as undefined. Fetch it via getattr so the runtime guard is
  explicit and static analysis passes on every platform; behavior is
  unchanged (returns None when sysconf is unavailable).
- _relativize_sources: os.path.relpath yields backslash separators on
  Windows, so exported source paths (and the corresponding test) diverged
  from the POSIX form. Normalize to forward slashes so exports match across
  platforms.

ci-local.ps1 now reports all five checks passing on Windows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Windows reproduction helper used ctypes.windll / ctypes.WinError /
wintypes, which are absent from the ctypes stubs on non-Windows platforms, so
mypy failed on the Linux CI (it passed locally on Windows). Reach windll via
getattr, use c_void_p for the HANDLE, and raise a plain OSError instead of
WinError. Behavior on Windows is unchanged; verified with
`mypy src tests --platform linux`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@buzzer-re
buzzer-re merged commit b6d7f1c into main Jul 23, 2026
4 checks passed
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.

Parallel write conflicts with -j N flag

1 participant