Serialize Gradle containers sharing a cache volume #22
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fm/wolfskin-14-gradle-lock"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Change
Acquire a host-side flock before running Gradle containers, keeping it through container exit. Contending callers print one waiting line and queue. Default:
/var/tmp/${WOLFSKIN_GRADLE_VOLUME}.gradle.lock, withwolfskin-gradleas the volume default; override withWOLFSKIN_GRADLE_LOCK_FILE. This intentionally differs from the temporary outer/tmp/wolfskin-gradle.lockused by other lanes. Document dependencies and the shared-path requirement.Reconciliation
Fetched origin/main at
761a5a6145809d00e951e44698ae6c461c3585a3; its docker/gradle.sh has no host lock. Live Docker has the wolfskin-gradle named volume (created October 22); no Wolfskin app container or pre-existing build image was present. This changes the build wrapper only, not app deployment.Verification
bash -n docker/gradle.shpassed. Started two realmake apk-debugcommands together, without outer flock; both exited 0. UTC timestamps:Second invocation printed exactly one
Waiting for Gradle cache lock: /var/tmp/wolfskin-gradle.gradle.lockbefore Gradle ran. Docker image builds can overlap; Gradle containers queue. Full logs are under/root/.treehouse/firstmate-7bab20/2/firstmate/data/wolfskin-14-gradle-lock/build-{1,2}.log.Constraints
All callers sharing a Docker volume must use the same host lock path; do not unlink the lock while callers run or wait. Callers bypassing the wrapper are not serialized. Forgejo Actions is disabled; no CI status is expected. AI-assisted implementation and PR description.
Closes justinzeus/wolfskin#14
Review verdict: approve (no blocking findings) — reviewed SHA
221f623c871bf2a041fe5416a02b00d623864df4, code review by Claude. Closes the Gradle-cache-lock ticket (justinzeus/wolfskin#14).Checked
exec {lock_fd}>"$lock"+flockhappen beforedocker run, anddocker runis a child of the script (noexec), so the fd stays open until the script exits. Stub-docker test: B'sdocker-entercame 7 ms after A'sdocker-exit(3 s runs), B printed oneWaiting for Gradle cache lock: ...line.docker/gradle.sh debug --versionstarted together (no outer flock) both exited 0; one printed the waiting line; they finished 5.4 s and 7.4 s after start, i.e. queued.build-1.log/build-2.log): both started 14:21:07.63Z; first ended 14:27:28Z; second printed the single waiting line, thenBUILD SUCCESSFUL in 2m 50sending 14:30:22Z, so its Gradle started about 14:27:32Z, after the first finished. Both EXIT 0.flock /tmp/wolfskin-gradle.lock make ...: default lock is/var/tmp/wolfskin-gradle.gradle.lock, a different file. Verifiedflock /tmp/wolfskin-gradle.lock bash docker/gradle.sh ...returns rc=0 immediately.WOLFSKIN_GRADLE_LOCK_FILEworks (custom path created, A/B queued on it). DifferentWOLFSKIN_GRADLE_VOLUMEvalues get independent locks and run in parallel.x.lock: No such file or directory, rc=1. README mentions the lock, default, override, and shared-path requirement.Notes (non-blocking)
flockbinary does fail (rc=127) but the output is misleading:flock: command not found, then a bogusWaiting for Gradle cache lock: ..., then a secondcommand not found, becauseif ! flock --nonblocktreats 127 as "contended". Acommand -v flockguard, or checking for exit status 1 specifically, would make it clean. The README does listflockas a prerequisite.0600root. Callers running as different uids on the same host would get a permission error opening it; fine while every lane is root.docker runsurvives, the lock stays held by the docker CLI until it exits (the safe direction).