The start pass reads a module's look-again mark after letting go, and hands it on to takeDoneKey (issue 1945)

This commit is contained in:
2026-10-25 13:00:43 +01:00
parent f35aa35541
commit c47a590463
2 changed files with 41 additions and 4 deletions
+12 -4
View File
@@ -355,11 +355,19 @@ const startTakeIns = 16
// which tries again every doneKeyRetry, loudly, so a failing module never holds up the look at the others.
func takeDoneKeyAtStart(ctx context.Context, open *stores, module string) {
mu, _ := doneKeysMu.LoadOrStore(module, &sync.Mutex{})
mu.(*sync.Mutex).Lock()
err := takeDoneKeyOnce(ctx, open, module)
if !mu.(*sync.Mutex).TryLock() {
// A take-in already follows the module: told to look again, it takes what the start would have (issue 1945).
doneKeysLookAgain.Store(module, true)
return
}
doneKeysLookAgain.Delete(module) // what this look reads covers every wake before it
err := doneKeyTakeOnce(ctx, open, module)
mu.(*sync.Mutex).Unlock()
if err != nil {
// A failure or a wait is followed by takeDoneKey, which says it and looks again (issue 1945).
// Read after letting go, as every holder of a module's lock does: a wake during this look only marked the module
// (the review of issue 1945).
_, again := doneKeysLookAgain.LoadAndDelete(module)
if err != nil || again {
// A failure, a wait or a wake meanwhile is followed by takeDoneKey, which says it and looks again.
inBackground(func() { takeDoneKey(ctx, open, module) })
}
}