Repository: go
Issue: runtime: respect SA_RESETHAND when forwarding to non-Go signal handler
Labels: NeedsFix

<!-- Please answer these questions before submitting your issue. Thanks! -->

### What version of Go are you using (`go version`)?

<pre>
go version go1.10.4 linux/amd64
</pre>

### Does this issue reproduce with the latest release?
Yes


### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/jim/go"
GORACE=""
GOROOT="/usr/lib/go-1.10"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.10/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build690985833=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?
- 1. Compile a library using -buildmode=c-shared
- 2. Trap SIGSEGV in a C program with a handler which will reraise SIGSEGV
- 3. Load the library against the C program using dlopen
- 4. Cause the C program to SEGSIGV by dereference a NULL pointer

src file: [infinitesignalloop.gz](https://github.com/golang/go/files/3298547/infinitesignalloop.gz)
to compile: uncompress src file to GOPATH and run `make`
to reproduce: just run  `./trap_signal before`

<!--
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.
-->

### What did you expect to see?
The program should crash finally with the default system segfault handler be called.
```
trap SIGSEGV before dlopen ./libdummycgo.so
Received Segmentation fault ...
Segmentation fault (core dumped)
```


### What did you see instead?
A infinite sighandling loop has happen.
```
trap SIGSEGV before dlopen ./libdummycgo.so
Received Segmentation fault ...
Received Segmentation fault ...
... // infinite loop
Received Segmentation fault ...
Killed
```
Following the code with gdb, it seems that Go signal handler raises SIGSEGV again to invoke the C handler, then C handler reraise SIGSEGV, which is catched by Go signal handler again, and then repeat and repeat.

As doc [https://golang.org/pkg/os/signal/#hdr-Go_programs_that_use_cgo_or_SWIG](url) said in section **Go programs that use cgo or SWIG** (not in section **Non-Go programs that call Go code**)

> If the Go signal handler is invoked on a non-Go thread not running Go code, the handler generally forwards the signal to the non-Go code, as follows. If the signal is SIGPROF, the Go handler does nothing. Otherwise, the Go handler removes itself, unblocks the signal, and raises it again, to invoke any non-Go handler or default system handler. If the program does not exit, the Go handler then reinstalls itself and continues execution of the program.

And if we trap SIGSEGV after load the library (just run `./trap_signal after`), there C program will just crash with system default handler called as expected.

Some more tests shows above issue exist for all synchronize signals (SIGBUS, SIGFPE, and SIGSEGV).

When not use dlopen to load the library, instead to link the library against to a C program as following, 
- 1. Compile a library using -buildmode=c-shared
- 2. Trap SIGSEGV in a C program with a handler which will reraise SIGSEGV
- 3. Link the library against the C program
- 4. Cause the C program to SEGSIGV by dereference a NULL pointer  
and then run the C program, it will crash with default segfault handler called.