summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2012-12-14 17:33:59 +1100
committerAlex Brainman <alex.brainman@gmail.com>2012-12-14 17:33:59 +1100
commit331a181f595bd28889a2eeef22fe2410e9e8626f (patch)
tree0c7a3aad31cde1f9222293d76f93848cf1f109fc /src/cmd
parent634ab3f25fd5862224c2f769997fa0ea7e164189 (diff)
downloadgo-331a181f595bd28889a2eeef22fe2410e9e8626f.tar.gz
cmd/go: handle os signals
Ignore signals during "go run" and wait for running child process to exit. Stop executing further tests during "go test", wait for running tests to exit and report error exit code. Original CL 6351053 by dfc. Fixes issue 3572. Fixes issue 3581. R=golang-dev, dave, rsc CC=golang-dev https://codereview.appspot.com/6903061
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/dist/build.c1
-rw-r--r--src/cmd/go/build.go31
-rw-r--r--src/cmd/go/run.go1
-rw-r--r--src/cmd/go/signal.go31
-rw-r--r--src/cmd/go/signal_notunix.go13
-rw-r--r--src/cmd/go/signal_unix.go14
-rw-r--r--src/cmd/go/test.go1
7 files changed, 82 insertions, 10 deletions
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index fca668ceb..13dbe0e81 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -1183,6 +1183,7 @@ static char *buildorder[] = {
"pkg/go/ast",
"pkg/go/parser",
"pkg/os/exec",
+ "pkg/os/signal",
"pkg/net/url",
"pkg/text/template/parse",
"pkg/text/template",
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 7e3d2f496..5f91227f1 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -548,7 +548,6 @@ func (b *builder) do(root *action) {
}
b.readySema = make(chan bool, len(all))
- done := make(chan bool)
// Initialize per-action execution state.
for _, a := range all {
@@ -596,10 +595,11 @@ func (b *builder) do(root *action) {
if a == root {
close(b.readySema)
- done <- true
}
}
+ var wg sync.WaitGroup
+
// Kick off goroutines according to parallelism.
// If we are using the -n flag (just printing commands)
// drop the parallelism to 1, both to make the output
@@ -609,19 +609,30 @@ func (b *builder) do(root *action) {
par = 1
}
for i := 0; i < par; i++ {
+ wg.Add(1)
go func() {
- for _ = range b.readySema {
- // Receiving a value from b.sema entitles
- // us to take from the ready queue.
- b.exec.Lock()
- a := b.ready.pop()
- b.exec.Unlock()
- handle(a)
+ defer wg.Done()
+ for {
+ select {
+ case _, ok := <-b.readySema:
+ if !ok {
+ return
+ }
+ // Receiving a value from b.readySema entitles
+ // us to take from the ready queue.
+ b.exec.Lock()
+ a := b.ready.pop()
+ b.exec.Unlock()
+ handle(a)
+ case <-interrupted:
+ setExitStatus(1)
+ return
+ }
}
}()
}
- <-done
+ wg.Wait()
}
// build is the action for building a single package or command.
diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go
index 0f41fa61b..88f57617e 100644
--- a/src/cmd/go/run.go
+++ b/src/cmd/go/run.go
@@ -84,6 +84,7 @@ func runStdin(cmdargs ...interface{}) {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
+ startSigHandlers()
if err := cmd.Run(); err != nil {
errorf("%v", err)
}
diff --git a/src/cmd/go/signal.go b/src/cmd/go/signal.go
new file mode 100644
index 000000000..e8ba0d365
--- /dev/null
+++ b/src/cmd/go/signal.go
@@ -0,0 +1,31 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os"
+ "os/signal"
+ "sync"
+)
+
+// interrupted is closed, if go process is interrupted.
+var interrupted = make(chan struct{})
+
+// processSignals setups signal handler.
+func processSignals() {
+ sig := make(chan os.Signal)
+ signal.Notify(sig, signalsToIgnore...)
+ go func() {
+ <-sig
+ close(interrupted)
+ }()
+}
+
+var onceProcessSignals sync.Once
+
+// startSigHandlers start signal handlers.
+func startSigHandlers() {
+ onceProcessSignals.Do(processSignals)
+}
diff --git a/src/cmd/go/signal_notunix.go b/src/cmd/go/signal_notunix.go
new file mode 100644
index 000000000..ef13c1919
--- /dev/null
+++ b/src/cmd/go/signal_notunix.go
@@ -0,0 +1,13 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build plan9 windows
+
+package main
+
+import (
+ "os"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt}
diff --git a/src/cmd/go/signal_unix.go b/src/cmd/go/signal_unix.go
new file mode 100644
index 000000000..489a73b83
--- /dev/null
+++ b/src/cmd/go/signal_unix.go
@@ -0,0 +1,14 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+package main
+
+import (
+ "os"
+ "syscall"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT}
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index efd14609a..555c6f50e 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -644,6 +644,7 @@ func (b *builder) runTest(a *action) error {
// running.
tick := time.NewTimer(testKillTimeout)
if err == nil {
+ startSigHandlers()
done := make(chan error)
go func() {
done <- cmd.Wait()