From 8d97b22aa8e565ff05c5e9209f13d2394e9706c8 Mon Sep 17 00:00:00 2001
From: Andrei Vagin <avagin@google.com>
Date: Tue, 13 Aug 2019 11:54:59 -0700
Subject: tests: print stack traces if test failed by timeout

PiperOrigin-RevId: 263184083
---
 test/syscalls/syscall_test_runner.go | 45 +++++++++++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 3 deletions(-)

(limited to 'test')

diff --git a/test/syscalls/syscall_test_runner.go b/test/syscalls/syscall_test_runner.go
index 5936d66ff..d1f9552a2 100644
--- a/test/syscalls/syscall_test_runner.go
+++ b/test/syscalls/syscall_test_runner.go
@@ -23,11 +23,13 @@ import (
 	"math"
 	"os"
 	"os/exec"
+	"os/signal"
 	"path/filepath"
 	"strconv"
 	"strings"
 	"syscall"
 	"testing"
+	"time"
 
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	"golang.org/x/sys/unix"
@@ -189,6 +191,8 @@ func runTestCaseRunsc(testBin string, tc gtest.TestCase, t *testing.T) {
 		"-log-format=text",
 		"-TESTONLY-unsafe-nonroot=true",
 		"-net-raw=true",
+		fmt.Sprintf("-panic-signal=%d", syscall.SIGTERM),
+		"-watchdog-action=panic",
 	}
 	if *overlay {
 		args = append(args, "-overlay")
@@ -220,8 +224,8 @@ func runTestCaseRunsc(testBin string, tc gtest.TestCase, t *testing.T) {
 
 	// Current process doesn't have CAP_SYS_ADMIN, create user namespace and run
 	// as root inside that namespace to get it.
-	args = append(args, "run", "--bundle", bundleDir, id)
-	cmd := exec.Command(*runscPath, args...)
+	rArgs := append(args, "run", "--bundle", bundleDir, id)
+	cmd := exec.Command(*runscPath, rArgs...)
 	cmd.SysProcAttr = &syscall.SysProcAttr{
 		Cloneflags: syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS,
 		// Set current user/group as root inside the namespace.
@@ -239,9 +243,44 @@ func runTestCaseRunsc(testBin string, tc gtest.TestCase, t *testing.T) {
 	}
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
+	sig := make(chan os.Signal, 1)
+	signal.Notify(sig, syscall.SIGTERM)
+	go func() {
+		s, ok := <-sig
+		if !ok {
+			return
+		}
+		t.Errorf("%s: Got signal: %v", tc.FullName(), s)
+		done := make(chan bool)
+		go func() {
+			dArgs := append(args, "-alsologtostderr=true", "debug", "--stacks", id)
+			cmd := exec.Command(*runscPath, dArgs...)
+			cmd.Stdout = os.Stdout
+			cmd.Stderr = os.Stderr
+			cmd.Run()
+			done <- true
+		}()
+
+		timeout := time.Tick(3 * time.Second)
+		select {
+		case <-timeout:
+			t.Logf("runsc debug --stacks is timeouted")
+		case <-done:
+		}
+
+		t.Logf("Send SIGTERM to the sandbox process")
+		dArgs := append(args, "debug",
+			fmt.Sprintf("--signal=%d", syscall.SIGTERM),
+			id)
+		cmd = exec.Command(*runscPath, dArgs...)
+		cmd.Stdout = os.Stdout
+		cmd.Stderr = os.Stderr
+		cmd.Run()
+	}()
 	if err = cmd.Run(); err != nil {
 		t.Errorf("test %q exited with status %v, want 0", tc.FullName(), err)
 	}
+	close(sig)
 }
 
 // filterEnv returns an environment with the blacklisted variables removed.
@@ -277,7 +316,7 @@ func main() {
 		fatalf("test-name flag must be provided")
 	}
 
-	log.SetLevel(log.Warning)
+	log.SetLevel(log.Info)
 	if *debug {
 		log.SetLevel(log.Debug)
 	}
-- 
cgit v1.2.3