From ac95e92829ae945c9005fb899e1567c4f83b0344 Mon Sep 17 00:00:00 2001 From: constansino Date: Thu, 5 Mar 2026 19:25:57 +0800 Subject: [PATCH] fix(watcher): guard debounced callback after Stop --- internal/watcher/clients.go | 8 +++++++- internal/watcher/watcher.go | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/watcher/clients.go b/internal/watcher/clients.go index a1f00f14..de1b80f4 100644 --- a/internal/watcher/clients.go +++ b/internal/watcher/clients.go @@ -318,6 +318,9 @@ func (w *Watcher) triggerServerUpdate(cfg *config.Config) { if w == nil || w.reloadCallback == nil || cfg == nil { return } + if w.stopped.Load() { + return + } now := time.Now() @@ -343,10 +346,13 @@ func (w *Watcher) triggerServerUpdate(cfg *config.Config) { w.serverUpdateTimer.Stop() } w.serverUpdateTimer = time.AfterFunc(delay, func() { + if w.stopped.Load() { + return + } w.clientsMutex.RLock() latestCfg := w.config w.clientsMutex.RUnlock() - if latestCfg == nil || w.reloadCallback == nil { + if latestCfg == nil || w.reloadCallback == nil || w.stopped.Load() { w.serverUpdateMu.Lock() w.serverUpdatePend = false w.serverUpdateMu.Unlock() diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go index c40fef7b..76e2dee5 100644 --- a/internal/watcher/watcher.go +++ b/internal/watcher/watcher.go @@ -6,6 +6,7 @@ import ( "context" "strings" "sync" + "sync/atomic" "time" "github.com/fsnotify/fsnotify" @@ -39,6 +40,7 @@ type Watcher struct { serverUpdateTimer *time.Timer serverUpdateLast time.Time serverUpdatePend bool + stopped atomic.Bool reloadCallback func(*config.Config) watcher *fsnotify.Watcher lastAuthHashes map[string]string @@ -119,6 +121,7 @@ func (w *Watcher) Start(ctx context.Context) error { // Stop stops the file watcher func (w *Watcher) Stop() error { + w.stopped.Store(true) w.stopDispatch() w.stopConfigReloadTimer() w.stopServerUpdateTimer()