Commit 4122319e authored by Elias Naur's avatar Elias Naur

misc/ios: forward SIGQUIT to the iOS program

When running tests that fails to complete within the test timeout,
the go tool sends the test program a SIGQUIT signal to print
backtraces. However, for tests running with an exec wrapper, the
resulting backtraces will come from the exec wrapper process and
not the test program.

Change the iOS exec wrapper to forward SIGQUIT signals to the lldb
python driver and change the driver to forward the signals to the
running test on the device.

Before:

$ GOARCH=arm64 go test forever_test.go
lldb: running program
SIGQUIT: quit
PC=0x10816fe m=0 sigcode=0

goroutine 54 [syscall]:
syscall.Syscall6(0x7, 0x16ab, 0xc000033dfc, 0x0, 0xc000116f30, 0x0, 0x0, 0xc000116f30, 0x0, 0x1328820)
	/Users/elias/go-tip/src/syscall/asm_darwin_amd64.s:41 +0x5 fp=0xc000033d48 sp=0xc000033d40 pc=0x10816d5
syscall.wait4(0x16ab, 0xc000033dfc, 0x0, 0xc000116f30, 0x90, 0x1200e00, 0x1)
	/Users/elias/go-tip/src/syscall/zsyscall_darwin_amd64.go:34 +0x7b fp=0xc000033dc0 sp=0xc000033d48 pc=0x107e4eb
syscall.Wait4(0x16ab, 0xc000033e4c, 0x0, 0xc000116f30, 0xc0000fd518, 0x0, 0x0)
	/Users/elias/go-tip/src/syscall/syscall_bsd.go:129 +0x51 fp=0xc000033e10 sp=0xc000033dc0 pc=0x107b7b1
os.(*Process).wait(0xc00008d440, 0x1095e2e, 0xc0000fd518, 0x0)
	/Users/elias/go-tip/src/os/exec_unix.go:38 +0x7b fp=0xc000033e80 sp=0xc000033e10 pc=0x109af2b
os.(*Process).Wait(0xc00008d440, 0xc000033fb0, 0x10, 0x11d1f00)
	/Users/elias/go-tip/src/os/exec.go:125 +0x2b fp=0xc000033eb0 sp=0xc000033e80 pc=0x109a47b
os/exec.(*Cmd).Wait(0xc0000b1ce0, 0xc000033f90, 0x11394df)
	/Users/elias/go-tip/src/os/exec/exec.go:463 +0x5b fp=0xc000033f28 sp=0xc000033eb0 pc=0x1136f0b
main.startDebugBridge.func1(0xc0000b1ce0, 0xc0000b8ae0, 0xc0000e2a80)
	/Users/elias/go-tip/misc/ios/go_darwin_arm_exec.go:314 +0x40 fp=0xc000033fc8 sp=0xc000033f28 pc=0x11a1980
runtime.goexit()
	/Users/elias/go-tip/src/runtime/asm_amd64.s:1360 +0x1 fp=0xc000033fd0 sp=0xc000033fc8 pc=0x10565a1
created by main.startDebugBridge
	/Users/elias/go-tip/misc/ios/go_darwin_arm_exec.go:313 +0x15f

...

After:

$ GOARCH=arm64 go test forever_test.go
lldb: running program
=== RUN   TestForever
SIGQUIT: quit
PC=0x100144e24 m=0 sigcode=0

...

goroutine 19 [select (no cases)]:
command-line-arguments.TestForever(0x1300b60f0)
	/Users/elias/go-tip/src/forever_test.go:6 +0x18
testing.tRunner(0x1300b60f0, 0x100211aa0)
	/Users/elias/go-tip/src/testing/testing.go:795 +0xa8
created by testing.(*T).Run
	/Users/elias/go-tip/src/testing/testing.go:840 +0x22c

...

Change-Id: I6b3cf1662d07a43ade0530842733b0944bee1ace
Reviewed-on: https://go-review.googlesource.com/112676
Run-TryBot: Elias Naur <elias.naur@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarHyang-Ah Hana Kim <hyangah@gmail.com>
parent d89ea410
...@@ -31,6 +31,7 @@ import ( ...@@ -31,6 +31,7 @@ import (
"net" "net"
"os" "os"
"os/exec" "os/exec"
"os/signal"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
...@@ -498,7 +499,22 @@ func run(appdir, bundleID string, args []string) error { ...@@ -498,7 +499,22 @@ func run(appdir, bundleID string, args []string) error {
lldb.Stdout = os.Stdout lldb.Stdout = os.Stdout
var out bytes.Buffer var out bytes.Buffer
lldb.Stderr = io.MultiWriter(&out, os.Stderr) lldb.Stderr = io.MultiWriter(&out, os.Stderr)
err = lldb.Run() err = lldb.Start()
if err == nil {
// Forward SIGQUIT to the lldb driver which in turn will forward
// to the running program.
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGQUIT)
proc := lldb.Process
go func() {
for sig := range sigs {
proc.Signal(sig)
}
}()
err = lldb.Wait()
signal.Stop(sigs)
close(sigs)
}
// If the program was not started it can be retried without papering over // If the program was not started it can be retried without papering over
// real test failures. // real test failures.
started := bytes.HasPrefix(out.Bytes(), []byte("lldb: running program")) started := bytes.HasPrefix(out.Bytes(), []byte("lldb: running program"))
...@@ -709,6 +725,7 @@ const resourceRules = `<?xml version="1.0" encoding="UTF-8"?> ...@@ -709,6 +725,7 @@ const resourceRules = `<?xml version="1.0" encoding="UTF-8"?>
const lldbDriver = ` const lldbDriver = `
import sys import sys
import os import os
import signal
exe, device_exe, args = sys.argv[1], sys.argv[2], sys.argv[3:] exe, device_exe, args = sys.argv[1], sys.argv[2], sys.argv[3:]
...@@ -747,6 +764,7 @@ for i in range(0, sigs.GetNumSignals()): ...@@ -747,6 +764,7 @@ for i in range(0, sigs.GetNumSignals()):
event = lldb.SBEvent() event = lldb.SBEvent()
running = False running = False
prev_handler = None
while True: while True:
if not listener.WaitForEvent(1, event): if not listener.WaitForEvent(1, event):
continue continue
...@@ -766,6 +784,8 @@ while True: ...@@ -766,6 +784,8 @@ while True:
sys.stderr.write(out) sys.stderr.write(out)
state = process.GetStateFromEvent(event) state = process.GetStateFromEvent(event)
if state in [lldb.eStateCrashed, lldb.eStateDetached, lldb.eStateUnloaded, lldb.eStateExited]: if state in [lldb.eStateCrashed, lldb.eStateDetached, lldb.eStateUnloaded, lldb.eStateExited]:
if running:
signal.signal(signal.SIGQUIT, prev_handler)
break break
elif state == lldb.eStateConnected: elif state == lldb.eStateConnected:
process.RemoteLaunch(args, env, None, None, None, None, 0, False, err) process.RemoteLaunch(args, env, None, None, None, None, 0, False, err)
...@@ -774,6 +794,10 @@ while True: ...@@ -774,6 +794,10 @@ while True:
process.Kill() process.Kill()
debugger.Terminate() debugger.Terminate()
sys.exit(1) sys.exit(1)
# Forward SIGQUIT to the program.
def signal_handler(signal, frame):
process.Signal(signal)
prev_handler = signal.signal(signal.SIGQUIT, signal_handler)
# Tell the Go driver that the program is running and should not be retried. # Tell the Go driver that the program is running and should not be retried.
sys.stderr.write("lldb: running program\n") sys.stderr.write("lldb: running program\n")
running = True running = True
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment