Skip to content

Commit

Permalink
auth: get rid of deadlocking channel passing scheme in simpleTokenTTL
Browse files Browse the repository at this point in the history
Just use the mutex instead.

Fixes etcd-io#7471
  • Loading branch information
Anthony Romano committed Mar 14, 2017
1 parent 5193965 commit 1b1fabe
Showing 1 changed file with 32 additions and 31 deletions.
63 changes: 32 additions & 31 deletions auth/simple_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,26 @@ import (
const (
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
defaultSimpleTokenLength = 16
)

// var for testing purposes
var (
simpleTokenTTL = 5 * time.Minute
simpleTokenTTLResolution = 1 * time.Second
)

type simpleTokenTTLKeeper struct {
tokens map[string]time.Time
addSimpleTokenCh chan string
resetSimpleTokenCh chan string
deleteSimpleTokenCh chan string
stopCh chan chan struct{}
deleteTokenFunc func(string)
tokensMu sync.Mutex
tokens map[string]time.Time
stopCh chan chan struct{}
deleteTokenFunc func(string)
}

func NewSimpleTokenTTLKeeper(deletefunc func(string)) *simpleTokenTTLKeeper {
stk := &simpleTokenTTLKeeper{
tokens: make(map[string]time.Time),
addSimpleTokenCh: make(chan string, 1),
resetSimpleTokenCh: make(chan string, 1),
deleteSimpleTokenCh: make(chan string, 1),
stopCh: make(chan chan struct{}),
deleteTokenFunc: deletefunc,
tokens: make(map[string]time.Time),
stopCh: make(chan chan struct{}),
deleteTokenFunc: deletefunc,
}
go stk.run()
return stk
Expand All @@ -66,37 +65,34 @@ func (tm *simpleTokenTTLKeeper) stop() {
}

func (tm *simpleTokenTTLKeeper) addSimpleToken(token string) {
tm.addSimpleTokenCh <- token
tm.tokens[token] = time.Now().Add(simpleTokenTTL)
}

func (tm *simpleTokenTTLKeeper) resetSimpleToken(token string) {
tm.resetSimpleTokenCh <- token
if _, ok := tm.tokens[token]; ok {
tm.tokens[token] = time.Now().Add(simpleTokenTTL)
}
}

func (tm *simpleTokenTTLKeeper) deleteSimpleToken(token string) {
tm.deleteSimpleTokenCh <- token
delete(tm.tokens, token)
}

func (tm *simpleTokenTTLKeeper) run() {
tokenTicker := time.NewTicker(simpleTokenTTLResolution)
defer tokenTicker.Stop()
for {
select {
case t := <-tm.addSimpleTokenCh:
tm.tokens[t] = time.Now().Add(simpleTokenTTL)
case t := <-tm.resetSimpleTokenCh:
if _, ok := tm.tokens[t]; ok {
tm.tokens[t] = time.Now().Add(simpleTokenTTL)
}
case t := <-tm.deleteSimpleTokenCh:
delete(tm.tokens, t)
case <-tokenTicker.C:
nowtime := time.Now()
tm.tokensMu.Lock()
for t, tokenendtime := range tm.tokens {
if nowtime.After(tokenendtime) {
tm.deleteTokenFunc(t)
delete(tm.tokens, t)
}
}
tm.tokensMu.Unlock()
case waitCh := <-tm.stopCh:
tm.tokens = make(map[string]time.Time)
waitCh <- struct{}{}
Expand All @@ -108,7 +104,7 @@ func (tm *simpleTokenTTLKeeper) run() {
type tokenSimple struct {
indexWaiter func(uint64) <-chan struct{}
simpleTokenKeeper *simpleTokenTTLKeeper
simpleTokensMu sync.RWMutex
simpleTokensMu sync.Mutex
simpleTokens map[string]string // token -> username
}

Expand All @@ -128,6 +124,7 @@ func (t *tokenSimple) genTokenPrefix() (string, error) {
}

func (t *tokenSimple) assignSimpleTokenToUser(username, token string) {
t.simpleTokenKeeper.tokensMu.Lock()
t.simpleTokensMu.Lock()

_, ok := t.simpleTokens[token]
Expand All @@ -138,18 +135,23 @@ func (t *tokenSimple) assignSimpleTokenToUser(username, token string) {
t.simpleTokens[token] = username
t.simpleTokenKeeper.addSimpleToken(token)
t.simpleTokensMu.Unlock()
t.simpleTokenKeeper.tokensMu.Unlock()
}

func (t *tokenSimple) invalidateUser(username string) {
if t.simpleTokenKeeper == nil {
return
}
t.simpleTokenKeeper.tokensMu.Lock()
t.simpleTokensMu.Lock()
defer t.simpleTokensMu.Unlock()

for token, name := range t.simpleTokens {
if strings.Compare(name, username) == 0 {
delete(t.simpleTokens, token)
t.simpleTokenKeeper.deleteSimpleToken(token)
}
}
t.simpleTokensMu.Unlock()
t.simpleTokenKeeper.tokensMu.Unlock()
}

func newDeleterFunc(t *tokenSimple) func(string) {
Expand All @@ -172,7 +174,6 @@ func (t *tokenSimple) disable() {
t.simpleTokenKeeper.stop()
t.simpleTokenKeeper = nil
}

t.simpleTokensMu.Lock()
t.simpleTokens = make(map[string]string) // invalidate all tokens
t.simpleTokensMu.Unlock()
Expand All @@ -182,14 +183,14 @@ func (t *tokenSimple) info(ctx context.Context, token string, revision uint64) (
if !t.isValidSimpleToken(ctx, token) {
return nil, false
}

t.simpleTokensMu.RLock()
defer t.simpleTokensMu.RUnlock()
t.simpleTokenKeeper.tokensMu.Lock()
t.simpleTokensMu.Lock()
username, ok := t.simpleTokens[token]
if ok {
t.simpleTokenKeeper.resetSimpleToken(token)
}

t.simpleTokensMu.Unlock()
t.simpleTokenKeeper.tokensMu.Unlock()
return &AuthInfo{Username: username, Revision: revision}, ok
}

Expand Down

0 comments on commit 1b1fabe

Please sign in to comment.