From 86e8a91412f2c577c93dcd437dd144e8548e71f8 Mon Sep 17 00:00:00 2001 From: Adam Chen Date: Sat, 5 Sep 2026 16:20:47 +0000 Subject: [PATCH 1/2] fix(integration): reduce harness startup flakiness --- integration/harness.go | 65 ++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/integration/harness.go b/integration/harness.go index ea6c5f1..eac1855 100644 --- a/integration/harness.go +++ b/integration/harness.go @@ -190,52 +190,43 @@ func (v *VirtualHarness) Start() chan error { if v.LogLevel == nil { v.LogLevel = new(slog.LevelDebug) } - startDelay := 0 * time.Millisecond + for idx := range v.Central.Routers { + n, err := core.NewNylon(v.Central, v.Local[idx], *v.LogLevel, "", map[string]any{ + "vnet": vn, + }, state.NylonOptions{DBG_log_wireguard: true}, v.Tunables) + if err != nil { + errChan <- err + return errChan + } + v.Nylons[idx].Store(n) + } + v.Net.Ready() + + startDelay := time.Duration(0) for idx, rt := range v.Central.Routers { sd := startDelay + n := v.Nylons[idx].Load() go func() { - time.Sleep(sd) - labels := pprof.Labels("nylon node", string(rt.Id)) - n, err := core.NewNylon(v.Central, v.Local[idx], *v.LogLevel, "", map[string]any{ - "vnet": vn, - }, state.NylonOptions{DBG_log_wireguard: true}, v.Tunables) - if err != nil { - errChan <- err - return + timer := time.NewTimer(sd) + select { + case <-timer.C: + case <-ctx.Done(): + if !timer.Stop() { + select { + case <-timer.C: + default: + } + } } - v.Nylons[idx].Store(n) + labels := pprof.Labels("nylon node", string(rt.Id)) pprof.Do(context.Background(), labels, func(_ context.Context) { - cErr := n.Start() - if cErr != nil { - errChan <- cErr - return + if err := n.Start(); err != nil { + errChan <- err } }) }() - startDelay += time.Millisecond * 500 // add a tiny delay so they don't try to handshake at the exact same time - } - // wait for all routers to start - for { - started := true - for idx, _ := range v.Central.Routers { - if v.Nylons[idx].Load() == nil { - started = false - break - } - } - if started { - break - } - select { - case <-ctx.Done(): - return errChan - case <-time.After(time.Millisecond * 50): - case err := <-errChan: - errChan <- err - return errChan - } + startDelay += 500 * time.Millisecond } - v.Net.Ready() return errChan } From 9b9c0f98a4bc286122c71fd5f87c0d54b9946d27 Mon Sep 17 00:00:00 2001 From: Adam Chen Date: Sat, 5 Sep 2026 16:33:57 +0000 Subject: [PATCH 2/2] fix(e2e): fix rare race --- e2e/harness.go | 17 +++++++++++++++++ e2e/healthcheck_test.go | 1 + 2 files changed, 18 insertions(+) diff --git a/e2e/harness.go b/e2e/harness.go index 2506678..8a7c5bc 100644 --- a/e2e/harness.go +++ b/e2e/harness.go @@ -212,6 +212,23 @@ func (h *Harness) WaitForStatus(t *testing.T, nodeName string, check func(*proto } } +func (h *Harness) WaitForTCPListener(t *testing.T, nodeName string, port int) { + t.Helper() + deadline := time.Now().Add(WaitTimeout) + var stdout, stderr string + var err error + for { + stdout, stderr, err = h.Exec(nodeName, []string{"ss", "-H", "-ltn", "sport", "=", fmt.Sprintf(":%d", port)}) + if err == nil && stdout != "" { + return + } + if time.Now().After(deadline) { + t.Fatalf("timed out waiting for TCP listener on node %s port %d: %v\nStdout: %s\nStderr: %s", nodeName, port, err, stdout, stderr) + } + time.Sleep(50 * time.Millisecond) + } +} + func (h *Harness) ReadStatus(nodeName string) (*protocol.StatusResponse, error) { stdout, _, err := h.Exec(nodeName, []string{"nylon", "status", "-i", "nylon0", "--json"}) if err != nil { diff --git a/e2e/healthcheck_test.go b/e2e/healthcheck_test.go index 1c8c6ce..b644bd7 100644 --- a/e2e/healthcheck_test.go +++ b/e2e/healthcheck_test.go @@ -117,6 +117,7 @@ func TestHealthcheckPing(t *testing.T) { msg := "hello from node 3" // listen on node 1 bg := h.ExecBackground("node1", []string{"nc", "-l", "8888"}) + h.WaitForTCPListener(t, "node1", 8888) // send on node 3 stdout, stderr, err = h.Exec("node3", []string{"bash", "-c", fmt.Sprintf("echo '%s' | nc -N 10.0.1.4 8888", msg)}) if err != nil {