From 333f764df3d78930a5a3097fc34ac1374b7c3187 Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Sat, 7 Jan 2017 17:41:00 -0800 Subject: [PATCH] cmd/go, misc: switch from breakpoint to SIGUSR2 The iOS test harness has set a breakpoint early in the life of Go programs so that it can change the current working directory using information only available from the host debugger. Somewhere in the upgrade to iOS 10 / XCode 8.2, breakpoints stopped working. This may be an LLDB bug, or a bug in the ios-deploy LLDB scripts, it's not clear. Work around the problem by giving up on breakpoints. Instead, early in the life of every test binary built for iOS, send (and ignore) a SIGUSR2 signal. The debugger will catch this, giving the script go_darwin_arm_exec a chance to change the working directory. For the iOS builders. Change-Id: I7476531985217d0c76bc176904c48379210576c2 Reviewed-on: https://go-review.googlesource.com/34926 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- misc/ios/go_darwin_arm_exec.go | 7 +++---- src/cmd/go/test.go | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/misc/ios/go_darwin_arm_exec.go b/misc/ios/go_darwin_arm_exec.go index 1eeb289c7d2..2a06528c1b6 100644 --- a/misc/ios/go_darwin_arm_exec.go +++ b/misc/ios/go_darwin_arm_exec.go @@ -99,7 +99,7 @@ func main() { // Approximately 1 in a 100 binaries fail to start. If it happens, // try again. These failures happen for several reasons beyond // our control, but all of them are safe to retry as they happen - // before lldb encounters the initial getwd breakpoint. As we + // before lldb encounters the initial SIGUSR2 stop. As we // know the tests haven't started, we are not hiding flaky tests // with this retry. for i := 0; i < 5; i++ { @@ -224,6 +224,7 @@ func run(bin string, args []string) (err error) { s.do(`process handle SIGHUP --stop false --pass true --notify false`) s.do(`process handle SIGPIPE --stop false --pass true --notify false`) s.do(`process handle SIGUSR1 --stop false --pass true --notify false`) + s.do(`process handle SIGUSR2 --stop true --pass false --notify true`) // sent by test harness s.do(`process handle SIGCONT --stop false --pass true --notify false`) s.do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work s.do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work @@ -236,11 +237,9 @@ func run(bin string, args []string) (err error) { return nil } - s.do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go - started = true - s.doCmd("run", "stop reason = breakpoint", 20*time.Second) + s.doCmd("run", "stop reason = signal SIGUSR2", 20*time.Second) // Move the current working directory into the faux gopath. if pkgpath != "src" { diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go index cdb167de75f..1ff02a68e1a 100644 --- a/src/cmd/go/test.go +++ b/src/cmd/go/test.go @@ -894,9 +894,13 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, if buildContext.GOOS == "darwin" { if buildContext.GOARCH == "arm" || buildContext.GOARCH == "arm64" { - t.NeedCgo = true + t.IsIOS = true + t.NeedOS = true } } + if t.TestMain == nil { + t.NeedOS = true + } for _, cp := range pmain.imports { if len(cp.coverVars) > 0 { @@ -1343,7 +1347,8 @@ type testFuncs struct { NeedTest bool ImportXtest bool NeedXtest bool - NeedCgo bool + NeedOS bool + IsIOS bool Cover []coverInfo } @@ -1444,7 +1449,7 @@ var testmainTmpl = template.Must(template.New("main").Parse(` package main import ( -{{if not .TestMain}} +{{if .NeedOS}} "os" {{end}} "testing" @@ -1460,8 +1465,10 @@ import ( _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} {{end}} -{{if .NeedCgo}} +{{if .IsIOS}} + "os/signal" _ "runtime/cgo" + "syscall" {{end}} ) @@ -1523,6 +1530,12 @@ func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts {{end}} func main() { +{{if .IsIOS}} + signal.Notify(make(chan os.Signal), syscall.SIGUSR2) + syscall.Kill(0, syscall.SIGUSR2) + signal.Reset(syscall.SIGUSR2) +{{end}} + {{if .CoverEnabled}} testing.RegisterCover(testing.Cover{ Mode: {{printf "%q" .CoverMode}},