diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go index 4e777c2df..9c5a3ab6b 100644 --- a/cmd/tailscale/cli/cli.go +++ b/cmd/tailscale/cli/cli.go @@ -8,8 +8,10 @@ package cli import ( "context" + "errors" "flag" "fmt" + "io" "log" "net" "os" @@ -169,21 +171,22 @@ func connect(ctx context.Context) (net.Conn, *ipn.BackendClient, context.Context } // pump receives backend messages on conn and pushes them into bc. -func pump(ctx context.Context, bc *ipn.BackendClient, conn net.Conn) { +func pump(ctx context.Context, bc *ipn.BackendClient, conn net.Conn) error { defer conn.Close() for ctx.Err() == nil { msg, err := ipn.ReadMsg(conn) if err != nil { if ctx.Err() != nil { - return + return ctx.Err() } - if !gotSignal.Get() { - log.Printf("ReadMsg: %v\n", err) + if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) { + return fmt.Errorf("%w (tailscaled stopped running?)", err) } - break + return err } bc.GotNotifyMsg(msg) } + return ctx.Err() } func strSliceContains(ss []string, s string) bool { diff --git a/cmd/tailscale/cli/ping.go b/cmd/tailscale/cli/ping.go index be9261038..3f08cc138 100644 --- a/cmd/tailscale/cli/ping.go +++ b/cmd/tailscale/cli/ping.go @@ -80,7 +80,8 @@ func runPing(ctx context.Context, args []string) error { prc <- pr } }) - go pump(ctx, bc, c) + pumpErr := make(chan error, 1) + go func() { pumpErr <- pump(ctx, bc, c) }() hostOrIP := args[0] ip, err := tailscaleIPFromArg(ctx, hostOrIP) @@ -101,6 +102,8 @@ func runPing(ctx context.Context, args []string) error { select { case <-timer.C: fmt.Printf("timeout waiting for ping reply\n") + case err := <-pumpErr: + return err case pr := <-prc: timer.Stop() if pr.Err != "" { diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index d5d7fa6f4..911656ad5 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -344,7 +344,8 @@ func runUp(ctx context.Context, args []string) error { startingOrRunning := make(chan bool, 1) // gets value once starting or running gotEngineUpdate := make(chan bool, 1) // gets value upon an engine update - go pump(pumpCtx, bc, c) + pumpErr := make(chan error, 1) + go func() { pumpErr <- pump(pumpCtx, bc, c) }() printed := !simpleUp var loginOnce sync.Once @@ -404,6 +405,8 @@ func runUp(ctx context.Context, args []string) error { case <-gotEngineUpdate: case <-pumpCtx.Done(): return pumpCtx.Err() + case err := <-pumpErr: + return err } // Special case: bare "tailscale up" means to just start @@ -456,6 +459,8 @@ func runUp(ctx context.Context, args []string) error { default: } return pumpCtx.Err() + case err := <-pumpErr: + return err } }