Skip to content
This repository was archived by the owner on Jul 13, 2025. It is now read-only.

Commit b70c0c5

Browse files
committed
ssh/tailssh: fix data race during execution of test
In tailssh.go:1284, (*sshSession).startNewRecording starts a fire-and-forget goroutine that can outlive the test that triggered its creation. Among other things, it uses ss.logf, and may call it after the test has already returned. Since we typically use (*testing.T).Logf as the logger, this results in a data race and causes flaky tests. Ideally, we should fix the root cause and/or use a goroutines.Tracker to wait for the goroutine to complete. But with the release approaching, it's too risky to make such changes now. As a workaround, we update the tests to use tstest.WhileTestRunningLogger, which logs to t.Logf while the test is running and disables logging once the test finishes, avoiding the race. While there, we also fix TestSSHAuthFlow not to use log.Printf. Updates tailscale#15568 Updates tailscale#7707 (probably related) Signed-off-by: Nick Khyl <nickk@tailscale.com>
1 parent 565ebbd commit b70c0c5

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

ssh/tailssh/tailssh_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"errors"
1717
"fmt"
1818
"io"
19-
"log"
2019
"net"
2120
"net/http"
2221
"net/http/httptest"
@@ -48,7 +47,6 @@ import (
4847
"tailscale.com/tsd"
4948
"tailscale.com/tstest"
5049
"tailscale.com/types/key"
51-
"tailscale.com/types/logger"
5250
"tailscale.com/types/logid"
5351
"tailscale.com/types/netmap"
5452
"tailscale.com/types/ptr"
@@ -230,7 +228,7 @@ func TestMatchRule(t *testing.T) {
230228
t.Run(tt.name, func(t *testing.T) {
231229
c := &conn{
232230
info: tt.ci,
233-
srv: &server{logf: t.Logf},
231+
srv: &server{logf: tstest.WhileTestRunningLogger(t)},
234232
}
235233
got, gotUser, gotAcceptEnv, err := c.matchRule(tt.rule)
236234
if err != tt.wantErr {
@@ -349,7 +347,7 @@ func TestEvalSSHPolicy(t *testing.T) {
349347
t.Run(tt.name, func(t *testing.T) {
350348
c := &conn{
351349
info: tt.ci,
352-
srv: &server{logf: t.Logf},
350+
srv: &server{logf: tstest.WhileTestRunningLogger(t)},
353351
}
354352
got, gotUser, gotAcceptEnv, match := c.evalSSHPolicy(tt.policy)
355353
if match != tt.wantMatch {
@@ -491,7 +489,7 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) {
491489
})
492490

493491
s := &server{
494-
logf: t.Logf,
492+
logf: tstest.WhileTestRunningLogger(t),
495493
lb: &localState{
496494
sshEnabled: true,
497495
matchingRule: newSSHRule(
@@ -553,7 +551,7 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) {
553551

554552
for _, tt := range tests {
555553
t.Run(tt.name, func(t *testing.T) {
556-
s.logf = t.Logf
554+
s.logf = tstest.WhileTestRunningLogger(t)
557555
tstest.Replace(t, &handler, tt.handler)
558556
sc, dc := memnet.NewTCPConn(src, dst, 1024)
559557
var wg sync.WaitGroup
@@ -621,7 +619,7 @@ func TestMultipleRecorders(t *testing.T) {
621619
})
622620

623621
s := &server{
624-
logf: t.Logf,
622+
logf: tstest.WhileTestRunningLogger(t),
625623
lb: &localState{
626624
sshEnabled: true,
627625
matchingRule: newSSHRule(
@@ -714,7 +712,7 @@ func TestSSHRecordingNonInteractive(t *testing.T) {
714712
})
715713

716714
s := &server{
717-
logf: t.Logf,
715+
logf: tstest.WhileTestRunningLogger(t),
718716
lb: &localState{
719717
sshEnabled: true,
720718
matchingRule: newSSHRule(
@@ -887,13 +885,15 @@ func TestSSHAuthFlow(t *testing.T) {
887885
},
888886
}
889887
s := &server{
890-
logf: log.Printf,
888+
logf: tstest.WhileTestRunningLogger(t),
891889
}
892890
defer s.Shutdown()
893891
src, dst := must.Get(netip.ParseAddrPort("100.100.100.101:2231")), must.Get(netip.ParseAddrPort("100.100.100.102:22"))
894892
for _, tc := range tests {
895893
for _, authMethods := range [][]string{nil, {"publickey", "password"}, {"password", "publickey"}} {
896894
t.Run(fmt.Sprintf("%s-skip-none-auth-%v", tc.name, strings.Join(authMethods, "-then-")), func(t *testing.T) {
895+
s.logf = tstest.WhileTestRunningLogger(t)
896+
897897
sc, dc := memnet.NewTCPConn(src, dst, 1024)
898898
s.lb = tc.state
899899
sshUser := "alice"
@@ -1036,7 +1036,7 @@ func TestSSHAuthFlow(t *testing.T) {
10361036
}
10371037

10381038
func TestSSH(t *testing.T) {
1039-
var logf logger.Logf = t.Logf
1039+
logf := tstest.WhileTestRunningLogger(t)
10401040
sys := tsd.NewSystem()
10411041
eng, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set, sys.HealthTracker(), sys.UserMetricsRegistry(), sys.Bus.Get())
10421042
if err != nil {

0 commit comments

Comments
 (0)