From fdf7798137a230b29fd34b2248c75ac6993eba83 Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Fri, 14 Apr 2017 09:50:33 -0700 Subject: [PATCH] auth: fix race on stopping simple token keeper run goroutine was resetting a field for no reason and without holding a lock. This patch cleans up the run goroutine management to make the start/stop path less racey in general. --- auth/simple_token.go | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/auth/simple_token.go b/auth/simple_token.go index cb7e8de28..94d92a115 100644 --- a/auth/simple_token.go +++ b/auth/simple_token.go @@ -42,16 +42,18 @@ var ( type simpleTokenTTLKeeper struct { tokens map[string]time.Time - stopCh chan chan struct{} + donec chan struct{} + stopc chan struct{} deleteTokenFunc func(string) mu *sync.Mutex } func (tm *simpleTokenTTLKeeper) stop() { - waitCh := make(chan struct{}) - tm.stopCh <- waitCh - <-waitCh - close(tm.stopCh) + select { + case tm.stopc <- struct{}{}: + case <-tm.donec: + } + <-tm.donec } func (tm *simpleTokenTTLKeeper) addSimpleToken(token string) { @@ -70,7 +72,10 @@ func (tm *simpleTokenTTLKeeper) deleteSimpleToken(token string) { func (tm *simpleTokenTTLKeeper) run() { tokenTicker := time.NewTicker(simpleTokenTTLResolution) - defer tokenTicker.Stop() + defer func() { + tokenTicker.Stop() + close(tm.donec) + }() for { select { case <-tokenTicker.C: @@ -83,9 +88,7 @@ func (tm *simpleTokenTTLKeeper) run() { } } tm.mu.Unlock() - case waitCh := <-tm.stopCh: - tm.tokens = make(map[string]time.Time) - waitCh <- struct{}{} + case <-tm.stopc: return } } @@ -148,7 +151,8 @@ func (t *tokenSimple) enable() { } t.simpleTokenKeeper = &simpleTokenTTLKeeper{ tokens: make(map[string]time.Time), - stopCh: make(chan chan struct{}), + donec: make(chan struct{}), + stopc: make(chan struct{}), deleteTokenFunc: delf, mu: &t.simpleTokensMu, } @@ -156,13 +160,14 @@ func (t *tokenSimple) enable() { } func (t *tokenSimple) disable() { - if t.simpleTokenKeeper != nil { - t.simpleTokenKeeper.stop() - t.simpleTokenKeeper = nil - } t.simpleTokensMu.Lock() + tk := t.simpleTokenKeeper + t.simpleTokenKeeper = nil t.simpleTokens = make(map[string]string) // invalidate all tokens t.simpleTokensMu.Unlock() + if tk != nil { + tk.stop() + } } func (t *tokenSimple) info(ctx context.Context, token string, revision uint64) (*AuthInfo, bool) {