Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setTokenHeader is not thread-safe #168

Open
andreyvit opened this issue Apr 23, 2020 · 0 comments
Open

setTokenHeader is not thread-safe #168

andreyvit opened this issue Apr 23, 2020 · 0 comments

Comments

@andreyvit
Copy link

Hey, I'm reading the source code prior to using this library in our app, and found a memory model violation when running in token mode.

The problem is with setTokenHeader:

func (c *Client) setTokenHeader(r *http.Request) {
	c.Token.GenerateIfExpired()
	r.Header.Set("authorization", fmt.Sprintf("bearer %v", c.Token.Bearer))
}

Here, a write to c.Token.Bearer (inside c.Token.GenerateIfExpired call) is protected by a mutex, but the corresponding read (within r.Header.Set(...) call) is unprotected.

This causes 2 problems:

  1. There is no happens-before relationship between writes to c.Token.Bearer and reads of it from other threads.

  2. Because string is larger than a single machine word, unsynchronized reads and writes may result in a partially-assigned value to be read.

This means that, if there's a constant multithreaded load, after refreshing the token the app might panic, or use the expired token, or use an incorrect token.

I have three choices of recommended fixes. Please pick the one you like.

Option 1, a minimal fix:

  1. Lock the mutex of c.Token for the duration of r.Header.Set call above.
  2. Document the current (weird) locking behavior of token APIs (GenerateIfExpired locks the mutex, all other method, notably Generate, does not).

Option 2, a better fix:

  1. Deprecate Token.GenerateIfExpired, it should never have messed with the mutex.
  2. Inline the call to GenerateIfExpired in setTokenHeader`, keeping the mutex locked for the entire duration of the call.
  3. Document that any accesses and calls to Token APIs should be synchronised via its mutex.

Option 3, if you don't care about keeping nuanced backwards compatibility of token API:

  1. Remove mutex locking from Token.GenerateIfExpired.
  2. Lock the token mutex for the duration of setTokenHeader call.
  3. Document that any accesses and calls to Token APIs should be synchronised via its mutex.

I'll be happy to send a PR for any of these.

@andreyvit andreyvit changed the title setTokenHeader is not thread-safe setTokenHeader is not thread-safe Apr 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant