cmd/containerboot: return context error when canceled during tailscale up/set
TestContainerBoot/kube_shutdown_during_state_write flaked with exit
code 1 instead of 0 when SIGTERM arrived while "tailscale up" was
still running. Two problems combined:
tailscaleUp and tailscaleSet wrapped errors with %v, flattening the
error chain, so main's errors.Is(err, context.Canceled) check could
not recognize a graceful shutdown.
Even with %w, cmd.Run under a canceled context usually reports the
death of the killed subprocess ("signal: killed") rather than the
context error that caused it, since Wait prefers the process error.
Check ctx.Err() explicitly and return it (wrapped with %w) so that
a shutdown-driven cancellation is recognized wherever it lands
relative to the subprocess lifetime.
Before: the exit-code failure reproduced 4 times in 808 stress runs
under CPU starvation. After: 0 in 1195 runs.
Fixes #19380
Change-Id: Ie15ca722d2d5ac2a3f79b2d0ab01fb71d4b9220d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
97a75c837d
commit
b93d9ba1ff
@@ -150,7 +150,15 @@ func tailscaleUp(ctx context.Context, cfg *settings) error {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("tailscale up failed: %v", err)
|
||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||
// A canceled context kills the command, and cmd.Run can
|
||||
// report the subprocess's death ("signal: killed") rather
|
||||
// than the context error that caused it. Return the
|
||||
// context error so that callers (and ultimately main) can
|
||||
// recognize a graceful shutdown with errors.Is.
|
||||
return fmt.Errorf("tailscale up failed: %w", ctxErr)
|
||||
}
|
||||
return fmt.Errorf("tailscale up failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -180,7 +188,11 @@ func tailscaleSet(ctx context.Context, cfg *settings) error {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("tailscale set failed: %v", err)
|
||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||
// See the equivalent check in tailscaleUp.
|
||||
return fmt.Errorf("tailscale set failed: %w", ctxErr)
|
||||
}
|
||||
return fmt.Errorf("tailscale set failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user