From 17c41a7dbe888abbccf5888702682741d95573a7 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Tue, 3 Oct 2023 11:16:33 +0200 Subject: [PATCH] fix: closed race condition --- serviceenabler.go | 69 ++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/serviceenabler.go b/serviceenabler.go index 3f06271..bfcdccc 100644 --- a/serviceenabler.go +++ b/serviceenabler.go @@ -21,7 +21,8 @@ type ServiceEnabler struct { syncEnabled bool syncEnabledLock sync.RWMutex enabledFn func() bool - closed bool + syncClosed bool + syncClosedLock sync.RWMutex } func NewServiceEnabler(l *zap.Logger, name string, serviceFn ServiceFunc, enabledFn func() bool) *ServiceEnabler { @@ -38,6 +39,44 @@ func (w *ServiceEnabler) Name() string { return w.name } +func (w *ServiceEnabler) Start(ctx context.Context) error { + w.watch() + w.ctx = ctx + if w.enabled() { + if err := w.enable(w.ctx); err != nil { + return err + } + } else { + w.l.Info("skipping disabled dynamic service") + } + return nil +} + +func (w *ServiceEnabler) Close(ctx context.Context) error { + l := log.WithServiceName(w.l, w.Name()) + w.setClosed(true) + if w.enabled() { + if err := w.disable(w.ctx); err != nil { + return err + } + } else { + l.Info("skipping disabled dynamic service") + } + return nil +} + +func (w *ServiceEnabler) closed() bool { + w.syncClosedLock.RLock() + defer w.syncClosedLock.RUnlock() + return w.syncClosed +} + +func (w *ServiceEnabler) setClosed(v bool) { + w.syncClosedLock.Lock() + defer w.syncClosedLock.Unlock() + w.syncClosed = v +} + func (w *ServiceEnabler) enabled() bool { w.syncEnabledLock.RLock() defer w.syncEnabledLock.RUnlock() @@ -66,7 +105,7 @@ func (w *ServiceEnabler) disable(ctx context.Context) error { func (w *ServiceEnabler) watch() { go func() { for { - if w.closed { + if w.closed() { break } time.Sleep(time.Second) @@ -86,29 +125,3 @@ func (w *ServiceEnabler) watch() { } }() } - -func (w *ServiceEnabler) Start(ctx context.Context) error { - w.watch() - w.ctx = ctx - if w.enabled() { - if err := w.enable(w.ctx); err != nil { - return err - } - } else { - w.l.Info("skipping disabled dynamic service") - } - return nil -} - -func (w *ServiceEnabler) Close(ctx context.Context) error { - l := log.WithServiceName(w.l, w.Name()) - w.closed = true - if w.enabled() { - if err := w.disable(w.ctx); err != nil { - return err - } - } else { - l.Info("skipping disabled dynamic service") - } - return nil -}