mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 02:00:52 +01:00
Stale-gate recovery proved a gate's holder dead from a pinned copy, then checked the shared path's identity with one lstat call and removed it with a separate, later unlink call. A fresh claimant's gate landing in the gap between those two calls was removed right along with the dead gate, letting a claim and a teardown run at the same time on one sandbox root. Recovery now removes the shared gate with a single rename, which atomically vacates the shared path and captures whatever it names at that instant. Only after the rename does recovery compare what it caught against the gate it already proved dead: a match deletes it for good, and a mismatch restores the caught, still-live gate immediately with link, which fails instead of overwriting a third claimant that grabbed the path first. The CI Build check also failed a related test on a fixed timing assumption: it moved a concurrently kicked-off claim forward with a short, real-time wait before reading the gate's content. A loaded CI runner can push the underlying filesystem calls well past that wait, matching a known timing gap already documented in this driver's host test file. Both content assertions in this file now poll for the expected state instead, bounded by a generous named deadline. A new test exercises the one race recovery's atomic removal cannot close on its own: a third claimant that grabs the shared path in the instant the capturing rename vacates it. Recovery must never clobber that claim, and must never lose the live gate it caught either. Co-authored-by: Paperclip <noreply@paperclip.ing>