Skip to main content

Module stopped_git_locks

Module stopped_git_locks 

Source
Expand description

The lock files a stopped Git child leaves behind, found and removed once the child and what it started are gone. What: The reference locks a stopped Git child may have left behind, judged and reported once the child and what it started are gone. Why: Git removes its .lock files when it ends normally or on a catchable signal, but a child that is killed, or that is in an uninterruptible call when the stop arrives, cannot. On 2026-11-03 two pushes were stopped at their deadline; about 37 seconds later, in the same instant, empty refs/remotes/origin/*.lock files appeared for exactly their two tracking refs, with no pid file beside them, and every later git fetch of those refs failed with “Unable to create … File exists”. The service had started those pushes without core.lockfilePid, so no pid file was written. That the creators were the stopped pushes, released by the kernel late, is the inference that fits these facts; nothing observed the processes themselves. Releases 0.5.23 to 0.5.26 removed two kinds of file after the stop: a lock whose pid file named an ended member of the stopped tree, and an empty lock without a pid file that was born after the child started and stayed empty for a settle time. A cross-vendor review of 2026-11-03T11:33:50-05:00 (finding S-1) showed that neither is an ownership proof: a live writer of another Git that does not write pid files holds its lock empty with no descriptor open, for as long as its transaction lasts, and a pid file older than a lock names an earlier holder, so both rules could delete the lock of a Git that is running, and two writers could then update one reference. The sweep removes nothing on those rules. It hands the repository to the same judgement that runs before every fetch and push (stale_ref_locks.rs), which removes a reference lock only on a proof and through a conditional removal, and it says what it found and which command clears a lock it will not remove. The judgement is given one proof of its own, which a container’s view of the machine cannot give it: the numbers of the processes of the stopped tree that have ended. A pid file born at or after a lock that was itself born after the child started, naming one of them, names a process the wrapper started and saw end, in its own namespace (the container gate found the sweep leaving its own child’s locks without it). Locks of other protocols (the index, the shallow file, object and pack locks) are not touched or mentioned.

In TS you’d write (pseudocode):

const ledger = LockLedger.beforeStart(command); const tree = await stop(child);
for (const lock of ledger.sweep(tree)) log(`removed ${lock}`);

Structs§

LockLedger
What: Where a command’s Git child can leave reference locks. Why: The sweep after a stop judges the locks of this repository, the one the child worked in; the time taken before the child started tells a lock born in its life from an older one.