fix: avoid truncating lock files before acquiring lock on Windows - #9269
fix: avoid truncating lock files before acquiring lock on Windows#9269aniruddhaadak80 wants to merge 1 commit into
Conversation
Design Review (Fable 5, fork) — ✅ PASSDesign-level review of All three removed skipifs were the only Design-Verdict: PASS Correctly retires the last fcntl-only, fail-open-on-Windows mutex onto the merged [DESIGN-REVIEWED] 1c804ec |
First Principles Review (Fable 5, fork) — 🟡 CONCERNSPremise-level review of All evidence gathered. The migration is mandated by the platform-compat spec table ( First-Principles-Verdict: CONCERNS The titled truncation fix removes nothing nameable — this lock file never carries content; the change's real, sufficient ground is the platform-compat Not justified as shipped
What this change shipsInventory (5 items) — 4 justifiedIntent: make the per-pod lifecycle mutex a real lock on Windows instead of a documented no-op — a FIX.
WatchThe "Why it matters" race is unreachable: "a stop that has just confirmed the service gone races a concurrent start" cannot happen on Windows, where [FIRST-PRINCIPLES-REVIEWED] 1c804ec |
GPT 5.6 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. |
Opus 4.8 Review (fork) — ✅ no blocking findingsReviewed |
A lock file opened with open(path, "w") is truncated before any lock is held; on Windows the acquire is msvcrt.locking on the already-truncated file, so a contending process can observe or produce an empty lock file and crash out of the critical section (kirodotdevGH-9248). Adds platform_compat.open_lock_file — a create-or-open (O_RDWR|O_CREAT, never truncating) opener yielding a raw fd for file_lock/flock_exclusive — and converts the four aws_control lock sites (backup, library, shares x2), the last unclaimed offenders after kirodotdev#9250/kirodotdev#9275/kirodotdev#9279/kirodotdev#9237. Pins the property fleet-wide: a contract test scans the source tree for truncating opens handed to a lock acquire, so a new offender fails with its file and line. deploy/pending.py and deploy/profiles.py are exempted while PR kirodotdev#9269 (which owns those sites) is in flight. Fixes kirodotdev#9248 (remaining sites).
ef31cca to
6ae9d0a
Compare
A lock file opened with open(path, "w") is truncated before any lock is held; on Windows the acquire is msvcrt.locking on the already-truncated file, so a contending process can observe or produce an empty lock file and crash out of the critical section (kirodotdevGH-9248). Adds platform_compat.open_lock_file — a create-or-open (O_RDWR|O_CREAT, never truncating) opener yielding a raw fd for file_lock/flock_exclusive — and converts the four aws_control lock sites (backup, library, shares x2), the last unclaimed offenders after kirodotdev#9250/kirodotdev#9275/kirodotdev#9279/kirodotdev#9237. Pins the property fleet-wide: a contract test scans the source tree for truncating opens handed to a lock acquire, so a new offender fails with its file and line. deploy/pending.py and deploy/profiles.py are exempted while PR kirodotdev#9269 (which owns those sites) is in flight. Fixes kirodotdev#9248 (remaining sites).
…9316) A lock file opened with open(path, "w") is truncated before any lock is held; on Windows the acquire is msvcrt.locking on the already-truncated file, so a contending process can observe or produce an empty lock file and crash out of the critical section (GH-9248). Adds platform_compat.open_lock_file — a create-or-open (O_RDWR|O_CREAT, never truncating) opener yielding a raw fd for file_lock/flock_exclusive — and converts the four aws_control lock sites (backup, library, shares x2), the last unclaimed offenders after #9250/#9275/#9279/#9237. Pins the property fleet-wide: a contract test scans the source tree for truncating opens handed to a lock acquire, so a new offender fails with its file and line. deploy/pending.py and deploy/profiles.py are exempted while PR #9269 (which owns those sites) is in flight. Fixes #9248 (remaining sites).
The fcntl-only pod_name_mutex degraded to a no-op without fcntl, so the open mode it used was unreachable on Windows and irrelevant on POSIX. Migrate it to platform_compat.file_lock over a touch+r+ lock file (the merged convention from kirodotdev#9237): real exclusion on Windows via msvcrt, unchanged blocking flock on POSIX. Drop the fcntl import and the three no-op skipifs; add cross-platform pins for the non-truncating open and same-thread re-entry.
6ae9d0a to
1c804ec
Compare
|
Reshaped into the real fix per the Design prescription (latest push, rebased onto current main, single commit):
|
Problem / Motivation
pod_name_mutex(src/kiro_crew/pod/runtime.py) used rawfcntl.flockand degraded to a no-op on hosts withoutfcntl-- so on Windows the pod lifecycle mutex serialized nothing, and its lock file was opened with truncating mode"w".Why it matters
downandupare independent entry points with no other per-name coordination, and both reclaim the isolated HOME on thedownpath. Without a working mutex on Windows, a stop that has just confirmed the service gone races a concurrent start whose checkout pin and service definition the stop's sweep would then delete.What changed (motivation → approach → change)
Migrated
pod_name_mutexto the merged cross-platform convention (cf. #9237 / GH-9248, as indeploy/pending.py):touch(exist_ok=True)+"r+"(writable, whichmsvcrt.lockingneeds, but non-truncating)platform_compat.file_lock(fcntl.flockon POSIX,msvcrt.lockingon Windows, fail-closed on both)if fcntl is None: yield; returnno-op branch and the now-unused guardedfcntlimport; docstring updatedTests
TestPodNameMutexCrossPlatform(test/test_pod.py, runs unskipped on every host): pins the non-truncating open (sentinel content survives acquisition) and same-thread re-entry (no deadlock). Both pass.rt.fcntl is Noneskipifs whose no-op premise no longer holds (concurrent port allocation, real-lock smoke, concurrent env writes); POSIX exclusion behavior is unchanged so those suites are unaffected.black --target-version py310,flake8,isort: clean on both touched files;mypyonpod/runtime.py: clean.Pattern harvest
Not generalizable: one-off migration of the last fcntl-only mutex to the established file_lock convention; no new pattern.
Related Issues
Related #9248 (lock-file truncation class); follows the convention merged in #9237.
Checklist
Contribution License Agreement