From 40dbf18893c33bc40c8617d0f3e8de16ce2947e2 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 17 Sep 2026 14:19:23 +0200 Subject: the applying flag is atomic; its test waits instead of polling The race detector found my own new flag: Apply writes it on a worker and Close reads it from the main loop. The test was polling a plain field too, where the real window hears about the apply on the main loop, which orders the writes. --- gui/internal/model/history.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'gui/internal/model/history.go') diff --git a/gui/internal/model/history.go b/gui/internal/model/history.go index 87ab6e7..d86984b 100644 --- a/gui/internal/model/history.go +++ b/gui/internal/model/history.go @@ -7,6 +7,7 @@ import ( "fmt" "sort" "strings" + "sync/atomic" "time" "git.labunix.xyz/krino/internal/engine" @@ -116,8 +117,8 @@ type UndoTab struct { locks []*lock.Lock // applying is set while the reversal is in flight; Close refuses then, - // for the reason PlanTab.applying gives. - applying bool + // for the reason PlanTab.applying gives. Atomic for the same reason. + applying atomic.Bool } // PlanUndo builds the reversal of runID and locks every directory it @@ -212,8 +213,8 @@ func (t *UndoTab) SelectedCount() int { // said no to (spec ยง9). Refused files ride along unchanged, as they do on // the command line. The locks are released afterwards: the plan is history. func (t *UndoTab) Apply(ctx context.Context) (*engine.ApplyResult, error) { - t.applying = true - defer func() { t.applying = false }() + t.applying.Store(true) + defer t.applying.Store(false) toApply := &engine.UndoPlan{Run: t.up.Run, Cleanup: t.up.Cleanup} for i, f := range t.up.Files { if f.Refused == "" && !t.Rows[i].Selected { @@ -272,7 +273,7 @@ func undoOutcome(row UndoRow, fr engine.FileResult) string { // does. One lock's failure never stops the rest from being released, or the // session from being closed. Closing twice is not an error. func (t *UndoTab) Close() error { - if t.applying { + if t.applying.Load() { return ErrApplying } var first error -- cgit v1.3