diff --git a/core/discov/internal/statewatcher.go b/core/discov/internal/statewatcher.go index d1b727fa..dc0f0296 100644 --- a/core/discov/internal/statewatcher.go +++ b/core/discov/internal/statewatcher.go @@ -18,7 +18,8 @@ type ( disconnected bool currentState connectivity.State listeners []func() - lock sync.Mutex + // lock only guards listeners, because only listens can be accessed by other goroutines. + lock sync.Mutex } ) @@ -32,27 +33,33 @@ func (sw *stateWatcher) addListener(l func()) { sw.lock.Unlock() } +func (sw *stateWatcher) notifyListeners() { + sw.lock.Lock() + defer sw.lock.Unlock() + + for _, l := range sw.listeners { + l() + } +} + +func (sw *stateWatcher) updateState(conn etcdConn) { + sw.currentState = conn.GetState() + switch sw.currentState { + case connectivity.TransientFailure, connectivity.Shutdown: + sw.disconnected = true + case connectivity.Ready: + if sw.disconnected { + sw.disconnected = false + sw.notifyListeners() + } + } +} + func (sw *stateWatcher) watch(conn etcdConn) { sw.currentState = conn.GetState() for { if conn.WaitForStateChange(context.Background(), sw.currentState) { - newState := conn.GetState() - sw.lock.Lock() - sw.currentState = newState - - switch newState { - case connectivity.TransientFailure, connectivity.Shutdown: - sw.disconnected = true - case connectivity.Ready: - if sw.disconnected { - sw.disconnected = false - for _, l := range sw.listeners { - l() - } - } - } - - sw.lock.Unlock() + sw.updateState(conn) } } } diff --git a/core/proc/shutdown+polyfill.go b/core/proc/shutdown+polyfill.go index 3fb1ddb5..13a48c44 100644 --- a/core/proc/shutdown+polyfill.go +++ b/core/proc/shutdown+polyfill.go @@ -4,10 +4,12 @@ package proc import "time" +// AddShutdownListener returns fn itself on windows, lets callers call fn on their own. func AddShutdownListener(fn func()) func() { return fn } +// AddWrapUpListener returns fn itself on windows, lets callers call fn on their own. func AddWrapUpListener(fn func()) func() { return fn }