From 715ba65563f9d2a6ecd349944b726a64f9aabeca Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 23 May 2022 16:27:13 -0400 Subject: [PATCH] misc/cgo/testsanitizers: terminate commands with SIGQUIT if hung 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 Run-TryBot: Bryan Mills Auto-Submit: Bryan Mills TryBot-Result: Gopher Robot --- misc/cgo/testsanitizers/cc_test.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go index d2f3bb1ed9..4f0252a27c 100644 --- a/misc/cgo/testsanitizers/cc_test.go +++ b/misc/cgo/testsanitizers/cc_test.go @@ -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) } } -- 2.50.0