mirror of
https://github.com/golang/go
synced 2024-11-19 14:34:42 -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")
|
throw("too many writes on closed pipe")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dieFromSignal(sig int32) {
|
||||||
|
exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
func sigpanic() {
|
func sigpanic() {
|
||||||
g := getg()
|
g := getg()
|
||||||
if !canpanic(g) {
|
if !canpanic(g) {
|
||||||
|
@ -142,8 +142,18 @@ func sigpipe() {
|
|||||||
if sigsend(_SIGPIPE) {
|
if sigsend(_SIGPIPE) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setsig(_SIGPIPE, _SIG_DFL, false)
|
dieFromSignal(_SIGPIPE)
|
||||||
raise(_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
|
// raisebadsignal is called when a signal is received on a non-Go
|
||||||
@ -196,9 +206,7 @@ func crash() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatesigmask(sigmask{})
|
dieFromSignal(_SIGABRT)
|
||||||
setsig(_SIGABRT, _SIG_DFL, false)
|
|
||||||
raise(_SIGABRT)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureSigM starts one global, sleeping thread to make sure at least one thread
|
// 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 {
|
if flags&_SigKill != 0 {
|
||||||
exit(2)
|
dieFromSignal(int32(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigThrow == 0 {
|
if flags&_SigThrow == 0 {
|
||||||
|
@ -140,7 +140,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigKill != 0 {
|
if flags&_SigKill != 0 {
|
||||||
exit(2)
|
dieFromSignal(int32(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigThrow == 0 {
|
if flags&_SigThrow == 0 {
|
||||||
|
@ -100,7 +100,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigKill != 0 {
|
if flags&_SigKill != 0 {
|
||||||
exit(2)
|
dieFromSignal(int32(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigThrow == 0 {
|
if flags&_SigThrow == 0 {
|
||||||
|
@ -116,7 +116,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigKill != 0 {
|
if flags&_SigKill != 0 {
|
||||||
exit(2)
|
dieFromSignal(int32(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigThrow == 0 {
|
if flags&_SigThrow == 0 {
|
||||||
|
@ -118,7 +118,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigKill != 0 {
|
if flags&_SigKill != 0 {
|
||||||
exit(2)
|
dieFromSignal(int32(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigThrow == 0 {
|
if flags&_SigThrow == 0 {
|
||||||
|
@ -122,7 +122,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigKill != 0 {
|
if flags&_SigKill != 0 {
|
||||||
exit(2)
|
dieFromSignal(int32(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags&_SigThrow == 0 {
|
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