@@ -28,6 +28,7 @@ import (
2828 "crypto/tls"
2929 "crypto/x509"
3030 "encoding/json"
31+ "errors"
3132 "fmt"
3233 "io"
3334 "math"
@@ -164,19 +165,36 @@ func TestMainnetE2E(t *testing.T) {
164165 defer func () {
165166 t .Log ("Stopping server..." )
166167 if cmd .Process != nil {
167- cmd .Process .Signal (syscall .SIGTERM )
168- // Wait with timeout
169168 done := make (chan error , 1 )
170169 go func () {
171170 done <- cmd .Wait ()
172171 }()
172+
173+ if err := signalServerProcessGroup (cmd , syscall .SIGTERM ); err != nil {
174+ t .Logf ("Failed to send SIGTERM: %v" , err )
175+ }
176+
173177 select {
174- case <- done :
178+ case err := <- done :
179+ if err != nil {
180+ t .Logf ("Server exited with error: %v" , err )
181+ }
175182 t .Log ("Server stopped gracefully" )
176183 case <- time .After (5 * time .Second ):
177184 t .Log ("Server did not stop gracefully, killing..." )
178- cmd .Process .Kill ()
179- cmd .Wait ()
185+ if err := signalServerProcessGroup (cmd , syscall .SIGKILL ); err != nil {
186+ t .Logf ("Failed to send SIGKILL: %v" , err )
187+ return
188+ }
189+
190+ select {
191+ case err := <- done :
192+ if err != nil {
193+ t .Logf ("Server exited with error after SIGKILL: %v" , err )
194+ }
195+ case <- time .After (5 * time .Second ):
196+ t .Log ("Server did not exit within 5s after SIGKILL" )
197+ }
180198 }
181199 }
182200 }()
@@ -297,6 +315,7 @@ func startServer(ctx context.Context, t *testing.T, binaryPath, dataDir, listenA
297315 // Redirect output to test logs
298316 cmd .Stdout = & testLogWriter {t : t , prefix : "[SERVER] " }
299317 cmd .Stderr = & testLogWriter {t : t , prefix : "[SERVER] " }
318+ cmd .SysProcAttr = & syscall.SysProcAttr {Setpgid : true }
300319
301320 if err := cmd .Start (); err != nil {
302321 t .Fatalf ("Failed to start server: %v" , err )
@@ -306,6 +325,19 @@ func startServer(ctx context.Context, t *testing.T, binaryPath, dataDir, listenA
306325 return cmd
307326}
308327
328+ func signalServerProcessGroup (cmd * exec.Cmd , sig syscall.Signal ) error {
329+ if cmd == nil || cmd .Process == nil {
330+ return nil
331+ }
332+
333+ // Signal the entire process group so any child processes do not outlive the parent.
334+ if err := syscall .Kill (- cmd .Process .Pid , sig ); err == nil || errors .Is (err , syscall .ESRCH ) {
335+ return nil
336+ }
337+
338+ return cmd .Process .Signal (sig )
339+ }
340+
309341// testLogWriter writes to test logs with a prefix
310342type testLogWriter struct {
311343 t * testing.T
0 commit comments