Holmake: add locking for concurrent safety (#1826)#1905
Holmake: add locking for concurrent safety (#1826)#1905
Conversation
When two separate Holmake processes build in directories that share a common dependency, both may try to rebuild the shared directory simultaneously, leading to race conditions and build failures. Fix this by acquiring a POSIX fcntl advisory lock on a per-directory lockfile (.hol/holmake.lock) before building targets in that directory. If another Holmake process is already building there, the second process blocks until the first finishes, then re-checks timestamps and skips targets that are already up-to-date. The locking is added to both build paths: - HM_GraphBuildJ1 (jobs=1): tracks the currently locked directory and acquires/releases on directory transitions. - multibuild (jobs>1): uses a refcount-based lock map since multiple jobs from different directories may be active concurrently. On non-Unix systems or if locking fails (e.g., unsupported filesystem), Holmake warns and proceeds without locking, preserving the previous behaviour.
|
if it's not too much extra work (or even the same amount of work?) per-file would be good for users too. actually strictly better i think |
I think it's a fair amount of more work for not that much benefit... but we could look into it... |
|
(This comment was generated by Claude) I analysed what per-file (per-target) locking would entail versus the current per-directory approach. Here is the summary: Complexity increase: Per-file locking is roughly 2-3x more code (~150-200 lines vs ~110). The main complications are:
Practical benefit is minimal for the reported use case: The issue describes two separate Holmake processes both needing the same shared directory X rebuilt. Both processes build all targets in X (since they depend on theories from X). With per-file locking, both would try to build the same files in the same dependency order, so they would just take turns on each file serially — same total wall-clock time as per-directory, but with more lock overhead. Per-file only helps if the two processes need different subsets of targets in X, which is uncommon. Where per-file would matter: If a future single Holmake with |
|
(This comment was generated by Claude) Correction to my earlier analysis: I was wrong that both processes would always need "all of directory X built". Holmake already does fine-grained dependency tracking via This means per-file locking has a more meaningful benefit than I originally claimed: if dirB needs theory A from shared X, and dirC needs theory B from X, per-directory locking forces dirC to wait while dirB builds A, even though they are working on independent targets. Per-file locking would allow both to proceed concurrently on their respective targets, only blocking when both actually touch the same file. So @charles-cooper's point is stronger than I gave it credit for. The complexity cost is still real (multi-target grouping for |
without looking at the actual implementation code i'm skeptical about this. you would just have |
|
The test-code seems as if it has to be run manually. Can you not include it in the build’s testing? |
createDirIfNecessary: handle the race where two concurrent Holmake processes both try to create the same directory (e.g., .hol/objs). Previously, the second process would crash with EEXIST. Now catch OS.SysErr on mkDir and re-check whether the path is already a directory, only failing if it isn't.
Add dirlock test to parallel_tests so it runs automatically during selftest builds (bin/build -t).
should be included now |
When two separate Holmake processes build in directories that share a common dependency, both may try to rebuild the shared directory simultaneously, leading to race conditions and build failures.
Fix this by acquiring a POSIX fcntl advisory lock on a per-directory lockfile (.hol/holmake.lock) before building targets in that directory. If another Holmake process is already building there, the second process blocks until the first finishes, then re-checks timestamps and skips targets that are already up-to-date.
The locking is added to both build paths:
On non-Unix systems or if locking fails (e.g., unsupported filesystem), Holmake warns and proceeds without locking, preserving the previous behaviour.