From aa075638082ff4c4949082c5a505e6e00f1d73aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 18 May 2026 15:31:51 +0200 Subject: [PATCH] test: wait for transition goroutines to exit TestTransitionThreadsWhileDoingRequests spawned transition goroutines that read mainThread.state via thread.shutdown(). isDone.Store(true) signalled them to stop but the test returned without waiting, so they could still be running when the next test's initPHPThreads wrote a fresh mainThread.state, producing a -race failure on macOS. --- phpmainthread_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/phpmainthread_test.go b/phpmainthread_test.go index d274991863..54722b0963 100644 --- a/phpmainthread_test.go +++ b/phpmainthread_test.go @@ -95,8 +95,9 @@ func TestTransitionThreadsWhileDoingRequests(t *testing.T) { t.Cleanup(Shutdown) var ( - isDone atomic.Bool - wg sync.WaitGroup + isDone atomic.Bool + wg sync.WaitGroup + transitionsWG sync.WaitGroup ) numThreads := 10 @@ -122,8 +123,10 @@ func TestTransitionThreadsWhileDoingRequests(t *testing.T) { // try all possible permutations of transition, transition every ms transitions := allPossibleTransitions(worker1Path, worker2Path) + transitionsWG.Add(numThreads) for i := range numThreads { go func(thread *phpThread, start int) { + defer transitionsWG.Done() for { for j := start; j < len(transitions); j++ { if isDone.Load() { @@ -158,6 +161,9 @@ func TestTransitionThreadsWhileDoingRequests(t *testing.T) { // we are finished as soon as all 1000 requests are done wg.Wait() isDone.Store(true) + // wait for transition goroutines to exit before Shutdown to avoid them + // racing with a subsequent test's initPHPThreads via mainThread.state + transitionsWG.Wait() } func TestFinishBootingAWorkerScript(t *testing.T) {