cmd/tailscale/cli: start WatchIPNBus before initial Start

This partially reverts f3d2fd2.

When that patch was written, the goroutine that responds to IPN notifications
could call `StartLoginInteractive`, creating a race condition that led to
flaky integration tests. We no longer call `StartLoginInteractive` in that
goroutine, so the race is now impossible.

Moving the `WatchIPNBus` call earlier ensures the CLI gets all necessary
IPN notifications, preventing a reauth from hanging.

Updates tailscale/corp#31476

Signed-off-by: Alex Chan <alexc@tailscale.com>
This commit is contained in:
Alex Chan 2025-09-15 23:20:38 +01:00
parent ac681360ee
commit 608975cca2

View File

@ -542,8 +542,18 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
} }
}() }()
running := make(chan bool, 1) // gets value once in state ipn.Running // Start watching the IPN bus before we call Start() or StartLoginInteractive(),
watchErr := make(chan error, 1) // or we could miss IPN notifications.
//
// In particular, if we're doing a force-reauth, we could miss the
// notification with the auth URL we should print for the user. The
// initial state could contain the auth URL, but only if IPN is in the
// NeedsLogin state -- sometimes it's in Starting, and we don't get the URL.
watcher, err := localClient.WatchIPNBus(watchCtx, ipn.NotifyInitialState)
if err != nil {
return err
}
defer watcher.Close()
// Special case: bare "tailscale up" means to just start // Special case: bare "tailscale up" means to just start
// running, if there's ever been a login. // running, if there's ever been a login.
@ -585,11 +595,8 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
} }
} }
watcher, err := localClient.WatchIPNBus(watchCtx, ipn.NotifyInitialState) running := make(chan bool, 1)
if err != nil { watchErr := make(chan error, 1)
return err
}
defer watcher.Close()
go func() { go func() {
var printed bool // whether we've yet printed anything to stdout or stderr var printed bool // whether we've yet printed anything to stdout or stderr