]> Cypherpunks repositories - gostls13.git/commitdiff
misc/cgo/testsanitizers: terminate commands with SIGQUIT if hung
authorBryan C. Mills <bcmills@google.com>
Mon, 23 May 2022 20:27:13 +0000 (16:27 -0400)
committerGopher Robot <gobot@golang.org>
Mon, 23 May 2022 21:33:54 +0000 (21:33 +0000)
If the test hangs due to a deadlock in a subprocess, we want a
goroutine dump of that process to figure out the nature of the
deadlock. SIGQUIT causes the Go runtime to produce exactly
such a dump (unless the runtime itself is badly deadlocked).

For #52998.

Change-Id: Id9b3ba89d8f705e14f6cd789353fc2b7f4774ad3
Reviewed-on: https://go-review.googlesource.com/c/go/+/407954
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

misc/cgo/testsanitizers/cc_test.go

index d2f3bb1ed9c3da49905e33d867ac6bd7a8ac3a78..4f0252a27cce9def21d84f3933efdd05f2645423 100644 (file)
@@ -20,6 +20,7 @@ import (
        "sync"
        "syscall"
        "testing"
+       "time"
        "unicode"
 )
 
@@ -90,9 +91,26 @@ func replaceEnv(cmd *exec.Cmd, key, value string) {
 // mustRun executes t and fails cmd with a well-formatted message if it fails.
 func mustRun(t *testing.T, cmd *exec.Cmd) {
        t.Helper()
-       out, err := cmd.CombinedOutput()
+       out := new(strings.Builder)
+       cmd.Stdout = out
+       cmd.Stderr = out
+
+       err := cmd.Start()
        if err != nil {
-               t.Fatalf("%#q exited with %v\n%s", strings.Join(cmd.Args, " "), err, out)
+               t.Fatalf("%v: %v", cmd, err)
+       }
+
+       if deadline, ok := t.Deadline(); ok {
+               timeout := time.Until(deadline)
+               timeout -= timeout / 10 // Leave 10% headroom for logging and cleanup.
+               timer := time.AfterFunc(timeout, func() {
+                       cmd.Process.Signal(syscall.SIGQUIT)
+               })
+               defer timer.Stop()
+       }
+
+       if err := cmd.Wait(); err != nil {
+               t.Fatalf("%v exited with %v\n%s", cmd, err, out)
        }
 }