diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2026-04-05 13:47:51 +0000 |
|---|---|---|
| committer | Brad Fitzpatrick <brad@danga.com> | 2026-04-07 05:31:16 -0700 |
| commit | 2b1cfa7c4d55a438062cef08ae5f85e0ffad5305 (patch) | |
| tree | 830c65bad6bb057567e56548eced947cbeab2ae3 /control/controlhttp/controlhttpserver/controlhttpserver.go | |
| parent | 6e44c6828b501724b72a1bb31e51677b9e9f740b (diff) | |
| download | tailscale-2b1cfa7c4d55a438062cef08ae5f85e0ffad5305.tar.xz tailscale-2b1cfa7c4d55a438062cef08ae5f85e0ffad5305.zip | |
ssh/tailssh: fix race in session termination message delivery
When a recording upload fails mid-session, the recording goroutine
cancels the session context. This triggers two concurrent paths:
exec.CommandContext kills the process (causing cmd.Wait to return),
and killProcessOnContextDone tries to write the termination message
via exitOnce.Do. If cmd.Wait returns first, the main goroutine's
exitOnce.Do(func(){}) steals the once, and the termination message
is never written to the client.
Fix by waiting for killProcessOnContextDone to finish writing the
termination message (via <-ss.exitHandled) before claiming exitOnce,
when the context is already done.
Also fix the fallback path when launchProcess itself fails due to
context cancellation: use SSHTerminationMessage() with the correct
"\r\n\r\n" framing instead of fmt.Fprintf with the internal error
string.
Deflakes TestSSHRecordingCancelsSessionsOnUploadFailure, which was
failing consistently at a low rate due to the exitOnce race. After
this fix, flakestress passes with 8,668 runs, 0 failures.
Fixes #7707 (again. hopefully for good.)
Change-Id: I5ab911c71574db8d3f9d979fb839f273be51ecf9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Diffstat (limited to 'control/controlhttp/controlhttpserver/controlhttpserver.go')
0 files changed, 0 insertions, 0 deletions
