]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix exit status when killed by signal
authorIan Lance Taylor <iant@golang.org>
Fri, 1 Jan 2016 23:44:12 +0000 (15:44 -0800)
committerIan Lance Taylor <iant@golang.org>
Tue, 5 Jan 2016 18:00:33 +0000 (18:00 +0000)
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>

src/runtime/crash_unix_test.go
src/runtime/os_nacl.go
src/runtime/signal1_unix.go
src/runtime/signal_386.go
src/runtime/signal_amd64x.go
src/runtime/signal_arm.go
src/runtime/signal_arm64.go
src/runtime/signal_mips64x.go
src/runtime/signal_ppc64x.go
src/runtime/testdata/testprog/signal.go [new file with mode: 0644]

index b925d028aaf34fcffc4fdfd228aaf89ae139f78f..59425271c5820448271dddf5bf5c4666e6bcf477 100644 (file)
@@ -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)
+       }
+}
index 69eaf4c14e78322ec64176564619f37822ba902b..c7cc0a988905ea3c46c9ecbd04f7ee891b75892f 100644 (file)
@@ -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) {
index c2530322cc19a32977c3af6a5bd42de888f6bca5..4f4d2af6ea606fd87f16b00b6148245d23818cdb 100644 (file)
@@ -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
index 3ea0656e656f71901e35cede548fb65b96b37f44..5c53582f908e673f6e76c27fd75f76a3051526b7 100644 (file)
@@ -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 {
index ad3187337a4cf83aa5c758ef812f3ea0e0180e9a..834e85563c7757a1e0025bfc76eefae689966f37 100644 (file)
@@ -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 {
index e8d19a454d8c94df093a09951831aadd95fd953b..9ea48dff8a615b68d69969d9bec96d44dc48a191 100644 (file)
@@ -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 {
index 2966ec0b20be1293dd4262f73c8e67a950e1fdd1..9a83bf0c97f06c5e72cfe4bb1a795d57257041ca 100644 (file)
@@ -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 {
index f30ff6e9e9e57f2f57f2be4604035b359b2f2712..868e993104ae160a78a11a1e5c2822a71b2f3443 100644 (file)
@@ -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 {
index b22df8860210db8d0543eea8e2aa372a74d79cfc..ee263484aa4affc24e9dbfa273b6f5c603f8bb5a 100644 (file)
@@ -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 {
diff --git a/src/runtime/testdata/testprog/signal.go b/src/runtime/testdata/testprog/signal.go
new file mode 100644 (file)
index 0000000..ac2d3e8
--- /dev/null
@@ -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)
+}