.
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