From 99bde5a40670e28f589dcf5ca7c7e77dfcb424d5 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 10 Mar 2026 03:44:45 +0000 Subject: [PATCH] tstest/integration: deflake TestCollectPanic Two issues caused TestCollectPanic to flake: 1. ETXTBSY: The test exec'd the tailscaled binary directly without going through StartDaemon/awaitTailscaledRunnable, so it lacked the retry loop that other tests use to work around a mysterious ETXTBSY on GitHub Actions. 2. Shared filch files: The test didn't pass --statedir or TS_LOGS_DIR, so all parallel test instances wrote panic logs to the shared system state directory (~/.local/share/tailscale). Concurrent runs would clobber each other's filch log files, causing the second run to not find the panic data from the first. Fix both by adding awaitTailscaledRunnable before the first exec, and passing --statedir and TS_LOGS_DIR to isolate each test's log files, matching what StartDaemon does. It now passes x/tools/cmd/stress. Fixes #15865 Change-Id: If18b9acf8dbe9a986446a42c5d98de7ad8aae098 Signed-off-by: Brad Fitzpatrick --- tstest/integration/integration_test.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tstest/integration/integration_test.go b/tstest/integration/integration_test.go index 0482e4b53..19f9fa159 100644 --- a/tstest/integration/integration_test.go +++ b/tstest/integration/integration_test.go @@ -200,23 +200,34 @@ func TestExpectedFeaturesLinked(t *testing.T) { } func TestCollectPanic(t *testing.T) { - flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/15865") tstest.Shard(t) tstest.Parallel(t) env := NewTestEnv(t) n := NewTestNode(t, env) - cmd := exec.Command(env.daemon, "--cleanup") + // Wait for the binary to be executable, working around a + // mysterious ETXTBSY on GitHub Actions. + // See https://github.com/tailscale/tailscale/issues/15868. + if err := n.awaitTailscaledRunnable(); err != nil { + t.Fatal(err) + } + + logsDir := t.TempDir() + cmd := exec.Command(env.daemon, "--cleanup", "--statedir="+n.dir) cmd.Env = append(os.Environ(), "TS_PLEASE_PANIC=1", "TS_LOG_TARGET="+n.env.LogCatcherServer.URL, + "TS_LOGS_DIR="+logsDir, ) got, _ := cmd.CombinedOutput() // we expect it to fail, ignore err t.Logf("initial run: %s", got) // Now we run it again, and on start, it will upload the logs to logcatcher. - cmd = exec.Command(env.daemon, "--cleanup") - cmd.Env = append(os.Environ(), "TS_LOG_TARGET="+n.env.LogCatcherServer.URL) + cmd = exec.Command(env.daemon, "--cleanup", "--statedir="+n.dir) + cmd.Env = append(os.Environ(), + "TS_LOG_TARGET="+n.env.LogCatcherServer.URL, + "TS_LOGS_DIR="+logsDir, + ) if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("cleanup failed: %v: %q", err, out) }