C A\slock\syou\scan\ssee D 2026-09-28T12:35:23.070 E 2026-09-28T13:00:00 602fe970eef019f58ecb75260b782e4937c8d0cb N text/x-markdown U dmestas W 2539 # A lock you can see 0.3.32 made every writer take the repository's lock. 0.3.33 changes what the lock is. It used to be `flock` on the store file. `flock` does its job on a local disk, but it is not part of POSIX, and on a network filesystem it ranges from correct to silently locking nothing. Worse, from where a person sits, it is invisible. A writer blocked on it waits forever and says nothing, so one wedged process could stall every other writer to a repository with no sign of why. We lost three hours to exactly that while testing the last release. The lock is now a file, `.zit.lock`, created beside the store with `O_CREAT|O_EXCL`. The filesystem guarantees that only one process can create it, and that guarantee is defined by POSIX and holds on NFSv3 and later. git locks the same way, as do mail spools and pid files. The file says who holds it: a process id and a host. So a waiting writer can say what it is waiting for: ``` zit: waiting for the repository lock, held by process 4242 on build-host ``` and after a minute it gives up, names the holder, and names the file to delete if nothing is really using it. What a lock file costs is that it outlives a crash. A writer killed while holding the lock leaves the file behind. The next writer looks at who it names: a process on this machine that no longer exists means a stale lock, which it breaks. Breaking is itself locked, and removes the file only if it still names the dead process, so a writer can never remove a lock that a live process has just taken. A lock held from another machine can't be checked from here, so it is only ever waited for. That is also the advice: keep a repository on a network filesystem only if one process at a time writes to it. The rewrites, `zit pack` and `zit shun --force`, lock each other out with a second lock file, as before. They now also hold the writer lock across their last check and the rename that installs the new store. Until now a commit could land between the two and go into the store the rename threw away. The tests follow the lock. The simulation that interleaves several writers now kills them mid-write and requires the next one to break a dead holder's lock and never a live one's. The crash sweep over the rewrites stops at every lock operation too, and on its first run it found that the lock's own record needed an `fsync` to survive a power cut. The same release gives repositories made by `zit import-git` the project code that every sync peer checks, so a forge or a `fossil clone` accepts them. Z da0b70959698d800593d187b68111ff1