cmd/tailscale/cli: prevent concurrent Start calls in 'up'
Seems to deflake tstest/integration tests. I can't reproduce it anymore on one of my VMs that was consistently flaking after a dozen runs before. Now I can run hundreds of times. Updates #11649 Fixes #7036 Change-Id: I2f7d4ae97500d507bdd78af9e92cd1242e8e44b8 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
26f9bbc02b
commit
0fba9e7570
@ -496,11 +496,23 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
|
||||
running := make(chan bool, 1) // gets value once in state ipn.Running
|
||||
pumpErr := make(chan error, 1)
|
||||
|
||||
var printed bool // whether we've yet printed anything to stdout or stderr
|
||||
var loginOnce sync.Once
|
||||
startLoginInteractive := func() { loginOnce.Do(func() { localClient.StartLoginInteractive(ctx) }) }
|
||||
// localAPIMu should be held while doing mutable LocalAPI calls
|
||||
// to the backend. In particular, it prevents StartLoginInteractive from
|
||||
// being called from the watcher goroutine while the Start call from
|
||||
// the other goroutine is in progress.
|
||||
// See https://github.com/tailscale/tailscale/issues/7036#issuecomment-2053771466
|
||||
// TODO(bradfitz): simplify this once #11649 is cleaned up and Start is
|
||||
// hopefully removed.
|
||||
var localAPIMu sync.Mutex
|
||||
|
||||
startLoginInteractive := sync.OnceFunc(func() {
|
||||
localAPIMu.Lock()
|
||||
defer localAPIMu.Unlock()
|
||||
localClient.StartLoginInteractive(ctx)
|
||||
})
|
||||
|
||||
go func() {
|
||||
var printed bool // whether we've yet printed anything to stdout or stderr
|
||||
for {
|
||||
n, err := watcher.Next()
|
||||
if err != nil {
|
||||
@ -574,12 +586,14 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
|
||||
// Special case: bare "tailscale up" means to just start
|
||||
// running, if there's ever been a login.
|
||||
if simpleUp {
|
||||
localAPIMu.Lock()
|
||||
_, err := localClient.EditPrefs(ctx, &ipn.MaskedPrefs{
|
||||
Prefs: ipn.Prefs{
|
||||
WantRunning: true,
|
||||
},
|
||||
WantRunningSet: true,
|
||||
})
|
||||
localAPIMu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -596,10 +610,13 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := localClient.Start(ctx, ipn.Options{
|
||||
localAPIMu.Lock()
|
||||
err = localClient.Start(ctx, ipn.Options{
|
||||
AuthKey: authKey,
|
||||
UpdatePrefs: prefs,
|
||||
}); err != nil {
|
||||
})
|
||||
localAPIMu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if upArgs.forceReauth {
|
||||
|
Reference in New Issue
Block a user