mirror of
https://github.com/golang/go
synced 2024-11-19 13:04:45 -07:00
runtime: fix exit status when killed by signal
Previously, when a program died because of a SIGHUP, SIGINT, or SIGTERM signal it would exit with status 2. This CL fixes the runtime to exit with a status indicating that the program was killed by a signal. Change-Id: Ic2982a2562857edfdccaf68856e0e4df532af136 Reviewed-on: https://go-review.googlesource.com/18156 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
81b35117d9
commit
2c67c8c303
@ -133,3 +133,21 @@ func loop(i int, c chan bool) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
func TestSignalExitStatus(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
exe, err := buildTestProg(t, "testprog")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = testEnv(exec.Command(exe, "SignalExitStatus")).Run()
|
||||
if err == nil {
|
||||
t.Error("test program succeeded unexpectedly")
|
||||
} else if ee, ok := err.(*exec.ExitError); !ok {
|
||||
t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
|
||||
} else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
|
||||
t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
|
||||
} else if !ws.Signaled() || ws.Signal() != syscall.SIGTERM {
|
||||
t.Errorf("got %v; expected SIGTERM", ee)
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ func os_sigpipe() {
|
||||
throw("too many writes on closed pipe")
|
||||
}
|
||||
|
||||
func dieFromSignal(sig int32) {
|
||||
exit(2)
|
||||
}
|
||||
|
||||
func sigpanic() {
|
||||
g := getg()
|
||||
if !canpanic(g) {
|
||||
|
@ -142,8 +142,18 @@ func sigpipe() {
|
||||
if sigsend(_SIGPIPE) {
|
||||
return
|
||||
}
|
||||
setsig(_SIGPIPE, _SIG_DFL, false)
|
||||
raise(_SIGPIPE)
|
||||
dieFromSignal(_SIGPIPE)
|
||||
}
|
||||
|
||||
// dieFromSignal kills the program with a signal.
|
||||
// This provides the expected exit status for the shell.
|
||||
// This is only called with fatal signals expected to kill the process.
|
||||
func dieFromSignal(sig int32) {
|
||||
setsig(sig, _SIG_DFL, false)
|
||||
updatesigmask(sigmask{})
|
||||
raise(sig)
|
||||
// That should have killed us; call exit just in case.
|
||||
exit(2)
|
||||
}
|
||||
|
||||
// raisebadsignal is called when a signal is received on a non-Go
|
||||
@ -196,9 +206,7 @@ func crash() {
|
||||
}
|
||||
}
|
||||
|
||||
updatesigmask(sigmask{})
|
||||
setsig(_SIGABRT, _SIG_DFL, false)
|
||||
raise(_SIGABRT)
|
||||
dieFromSignal(_SIGABRT)
|
||||
}
|
||||
|
||||
// ensureSigM starts one global, sleeping thread to make sure at least one thread
|
||||
|
@ -108,7 +108,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
|
@ -140,7 +140,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
|
@ -100,7 +100,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
|
@ -116,7 +116,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
|
@ -118,7 +118,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
|
@ -122,7 +122,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
|
17
src/runtime/testdata/testprog/signal.go
vendored
Normal file
17
src/runtime/testdata/testprog/signal.go
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2015 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 !windows,!plan9,!nacl
|
||||
|
||||
package main
|
||||
|
||||
import "syscall"
|
||||
|
||||
func init() {
|
||||
register("SignalExitStatus", SignalExitStatus)
|
||||
}
|
||||
|
||||
func SignalExitStatus() {
|
||||
syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
||||
}
|
Loading…
Reference in New Issue
Block a user