diff --git a/.github/workflows/test-bench.yml b/.github/workflows/test-bench.yml index 218a70a25c6..ca14d8e42c4 100644 --- a/.github/workflows/test-bench.yml +++ b/.github/workflows/test-bench.yml @@ -59,7 +59,29 @@ jobs: - name: Run benchmarks if: '!inputs.cache-warming-only' - run: make test-bench + # `go test -timeout` doesn't cover benchmarks (the testing alarm stops + # before the bench phase), so a hung benchmark would only die at the + # 60min job cap — which kills it with no diagnostics. This watchdog + # fires first at 45min: SIGQUIT makes the Go runtime dump all goroutine + # stacks into this step's log, pinpointing the stall, then fails the job. + run: | + ( + sleep 2700 + { + echo "## bench stall watchdog" + echo "test-bench exceeded 45min: sent SIGQUIT to the test binaries; goroutine dumps are in the 'Run benchmarks' step log" + } >> "$GITHUB_STEP_SUMMARY" + pkill -QUIT -f 'go-build.*\.test' || true + sleep 120 + pkill -KILL -f 'go-build.*\.test' || true + ) >/dev/null 2>&1 & + watchdog_pid=$! + cleanup() { + pkill -P "$watchdog_pid" 2>/dev/null || true + kill "$watchdog_pid" 2>/dev/null || true + } + trap cleanup EXIT + make test-bench - name: Build test binaries (cache warming) if: inputs.cache-warming-only