D48: a restore downloads first — every restore path resolves and pulls every image of the definition that will run before the stop, under the image-work lock held until the restore returns; a failed pull refuses with the app untouched (a deleted version and a busy registry read differently), one operator line. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s
gates / gates (push) Successful in 1m26s
This commit is contained in:
@@ -52,6 +52,16 @@ func BeginImageWork(args []string) (end func()) {
|
||||
return imageWorkMu.RUnlock
|
||||
}
|
||||
|
||||
// HoldImageWork holds the image-work lock SHARED until the returned func runs, whatever the verb (D48, 2026-10-25): a
|
||||
// restore resolves and pulls its images BEFORE it stops the app and starts them minutes later, so the clean-up must
|
||||
// not run anywhere in between. A compose command inside the hold takes the lock shared again (BeginImageWork); that
|
||||
// nests safely because the ONLY exclusive taker is TryImageCleanup's TryLock, which never waits — so no writer can be
|
||||
// queued between the two shared holds. Pinned by TestD48_HoldImageWorkBlocksCleanupAndNests.
|
||||
func HoldImageWork() (end func()) {
|
||||
imageWorkMu.RLock()
|
||||
return imageWorkMu.RUnlock
|
||||
}
|
||||
|
||||
// TryImageCleanup takes the image-work lock exclusively if no image work runs now. ok=false: something is
|
||||
// pulling — do not clean up now.
|
||||
func TryImageCleanup() (end func(), ok bool) {
|
||||
|
||||
Reference in New Issue
Block a user