summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-08 10:02:57 +0300
committerPaul Buetow <paul@buetow.org>2026-04-08 10:02:57 +0300
commitcfc7bb7bcf141b3d85ddcd597b4e71fc151ccc3f (patch)
treea540ddb5d8261cb4f0214e6bc4e459d9316f1f5d /internal
parent08d7d36ac6d49d7d5efd39a837bc08c9c52b6eb8 (diff)
fix(gui): avoid tooltip init race after window close
Use time.NewTimer with defer Stop in the delayed tooltip goroutine so the timer is not left pending when ctx wins the select. After the delay, check ctx before and inside fyne.Do so SetToolTip never runs after shutdown cancels the application context. Made-with: Cursor
Diffstat (limited to 'internal')
-rw-r--r--internal/gui/app.go14
1 files changed, 13 insertions, 1 deletions
diff --git a/internal/gui/app.go b/internal/gui/app.go
index 0c821d4..edb62ba 100644
--- a/internal/gui/app.go
+++ b/internal/gui/app.go
@@ -422,15 +422,27 @@ func (a *Application) setupUI() {
// Secondary toolbar button tooltips need a short delay to initialise.
// Tracked via WaitGroup and respects ctx.Done() so the callback never
// writes to freed widgets after the window is closed (Go Mistake #62).
+ // NewTimer (not time.After) avoids leaking a pending timer when ctx wins
+ // the select. After the delay, ctx is checked again before and inside
+ // fyne.Do: the timer can fire just before onWindowClosed cancels ctx, so
+ // the UI-thread callback must no-op if shutdown already started.
a.wg.Add(1)
go func() {
defer a.wg.Done()
+ t := time.NewTimer(500 * time.Millisecond)
+ defer t.Stop()
select {
case <-a.ctx.Done():
return
- case <-time.After(500 * time.Millisecond):
+ case <-t.C:
+ }
+ if a.ctx.Err() != nil {
+ return
}
fyne.Do(func() {
+ if a.ctx.Err() != nil {
+ return
+ }
if exportButton != nil {
exportButton.SetToolTip("Export to Anki (x)")
}