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.
@@ -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) {
