Commit 04f0d148 authored by Alex Brainman's avatar Alex Brainman

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 #3572.
Fixes #3581.

R=golang-dev, dave, rsc
CC=golang-dev
https://golang.org/cl/6903061
parent cc5682dc
...@@ -1183,6 +1183,7 @@ static char *buildorder[] = { ...@@ -1183,6 +1183,7 @@ static char *buildorder[] = {
"pkg/go/ast", "pkg/go/ast",
"pkg/go/parser", "pkg/go/parser",
"pkg/os/exec", "pkg/os/exec",
"pkg/os/signal",
"pkg/net/url", "pkg/net/url",
"pkg/text/template/parse", "pkg/text/template/parse",
"pkg/text/template", "pkg/text/template",
......
...@@ -548,7 +548,6 @@ func (b *builder) do(root *action) { ...@@ -548,7 +548,6 @@ func (b *builder) do(root *action) {
} }
b.readySema = make(chan bool, len(all)) b.readySema = make(chan bool, len(all))
done := make(chan bool)
// Initialize per-action execution state. // Initialize per-action execution state.
for _, a := range all { for _, a := range all {
...@@ -596,10 +595,11 @@ func (b *builder) do(root *action) { ...@@ -596,10 +595,11 @@ func (b *builder) do(root *action) {
if a == root { if a == root {
close(b.readySema) close(b.readySema)
done <- true
} }
} }
var wg sync.WaitGroup
// Kick off goroutines according to parallelism. // Kick off goroutines according to parallelism.
// If we are using the -n flag (just printing commands) // If we are using the -n flag (just printing commands)
// drop the parallelism to 1, both to make the output // drop the parallelism to 1, both to make the output
...@@ -609,19 +609,30 @@ func (b *builder) do(root *action) { ...@@ -609,19 +609,30 @@ func (b *builder) do(root *action) {
par = 1 par = 1
} }
for i := 0; i < par; i++ { for i := 0; i < par; i++ {
wg.Add(1)
go func() { go func() {
for _ = range b.readySema { defer wg.Done()
// Receiving a value from b.sema entitles for {
select {
case _, ok := <-b.readySema:
if !ok {
return
}
// Receiving a value from b.readySema entitles
// us to take from the ready queue. // us to take from the ready queue.
b.exec.Lock() b.exec.Lock()
a := b.ready.pop() a := b.ready.pop()
b.exec.Unlock() b.exec.Unlock()
handle(a) handle(a)
case <-interrupted:
setExitStatus(1)
return
}
} }
}() }()
} }
<-done wg.Wait()
} }
// build is the action for building a single package or command. // build is the action for building a single package or command.
......
...@@ -84,6 +84,7 @@ func runStdin(cmdargs ...interface{}) { ...@@ -84,6 +84,7 @@ func runStdin(cmdargs ...interface{}) {
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
startSigHandlers()
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
errorf("%v", err) errorf("%v", err)
} }
......
// 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)
}
// 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}
// 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}
...@@ -644,6 +644,7 @@ func (b *builder) runTest(a *action) error { ...@@ -644,6 +644,7 @@ func (b *builder) runTest(a *action) error {
// running. // running.
tick := time.NewTimer(testKillTimeout) tick := time.NewTimer(testKillTimeout)
if err == nil { if err == nil {
startSigHandlers()
done := make(chan error) done := make(chan error)
go func() { go func() {
done <- cmd.Wait() done <- cmd.Wait()
......
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