Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os/signal: sometimes SIGINT is not delivered #21905

Closed
ghost opened this issue Sep 16, 2017 · 6 comments
Closed

os/signal: sometimes SIGINT is not delivered #21905

ghost opened this issue Sep 16, 2017 · 6 comments

Comments

@ghost
Copy link

ghost commented Sep 16, 2017

What version of Go are you using (go version)?

1.9 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/opennota/gocode"
GORACE=""
GOROOT="/home/opennota/go"
GOTOOLDIR="/home/opennota/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build828076735=/tmp/go-build -gno-record-gcc-switches"
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"

What did you do?

c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
	<-c
	fmt.Println("interrupt")
	os.Exit(0)
}()

The complete program (it uses CImg via cgo): https://github.com/opennota/sigint_issue

I build the program, run it and after some waiting press Ctrl+C to terminate it.

What did you expect to see?

SIGINT delivered, the program printed "interrupt" and exited.

What did you see instead?

Sometimes pressing Ctrl+C doesn't stop the program, and it continues to run indefinitely. No "interrupt" is printed.

@ianlancetaylor
Copy link
Member

As the os/signal package documents, you should always use a buffered channel with signal.Notify. See what happens if you write

c := make(chan os.Signal, 1)

@ghost
Copy link
Author

ghost commented Sep 16, 2017

I've updated the repository. With a buffered channel it's the same: sometimes the signal is lost.

@davecheney
Copy link
Contributor

davecheney commented Sep 16, 2017 via email

@ghost
Copy link
Author

ghost commented Sep 16, 2017

Does the problem occur without using cgo?

It occurs with cgo (not all cgo, though: a simpler function instead of C.load doesn't seem to lose signals).

@mafredri
Copy link

mafredri commented Sep 16, 2017

Running the sigint_issue code on Darwin (macOS 10.12.6) and Go 1.9, after pressing ^C, I see a bunch of fatal: morestack on g0 printed out followed by a stack trace. As originally reported, sometimes ^C does not propagate and I have to send it multiple times. Not sure how relevant to the issue (and perhaps platform specific), posting here anyway in case it can give any hints.

go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/mafredri/Golang"
GORACE=""
GOROOT="/usr/local/opt/go/libexec"
GOTOOLDIR="/usr/local/opt/go/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/6l/ksm8qvls323c5tkg1t7bq2100000gn/T/go-build107050027=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
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"
fatal: morestack on g0
^Cfatal: morestack on g0
[repeated 840 times...]
fatal: morestack on g0
fatal: morestack on g0
SIGTRAP: trace trap
PC=0x4052ab2 m=0 sigcode=1

goroutine 0 [idle]:
runtime.morestack()
	/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:385 +0x22

goroutine 1 [select (no cases)]:
main.main()
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:28 +0x117

goroutine 5 [syscall]:
os/signal.signal_recv(0x0)
	/usr/local/opt/go/libexec/src/runtime/sigqueue.go:131 +0xa7
os/signal.loop()
	/usr/local/opt/go/libexec/src/os/signal/signal_unix.go:22 +0x22
created by os/signal.init.0
	/usr/local/opt/go/libexec/src/os/signal/signal_unix.go:28 +0x41

goroutine 6 [select, locked to thread]:
runtime.gopark(0x410c400, 0x0, 0x4105531, 0x6, 0x18, 0x1)
	/usr/local/opt/go/libexec/src/runtime/proc.go:277 +0x12c
runtime.selectgo(0xc420036f50, 0xc4200720c0)
	/usr/local/opt/go/libexec/src/runtime/select.go:395 +0x1138
runtime.ensureSigM.func1()
	/usr/local/opt/go/libexec/src/runtime/signal_unix.go:511 +0x1fe
runtime.goexit()
	/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:2337 +0x1

goroutine 7 [chan receive]:
main.main.func1(0xc420066060)
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:16 +0x38
created by main.main
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:15 +0xb5

goroutine 8 [syscall, locked to thread]:
main._Cfunc_load(0x4500020)
	github.com/opennota/sigint_issue/_obj/_cgo_gotypes.go:51 +0x41
main.main.func2(0x4500020)
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:24 +0x2b
created by main.main
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:22 +0xfe

goroutine 9 [syscall, locked to thread]:
main._Cfunc_load(0x4500020)
	github.com/opennota/sigint_issue/_obj/_cgo_gotypes.go:51 +0x41
main.main.func2(0x4500020)
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:24 +0x2b
created by main.main
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:22 +0xfe

goroutine 10 [syscall, locked to thread]:
main._Cfunc_load(0x4500020)
	github.com/opennota/sigint_issue/_obj/_cgo_gotypes.go:51 +0x41
main.main.func2(0x4500020)
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:24 +0x2b
created by main.main
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:22 +0xfe

goroutine 11 [syscall, locked to thread]:
main._Cfunc_load(0x4500020)
	github.com/opennota/sigint_issue/_obj/_cgo_gotypes.go:51 +0x41
main.main.func2(0x4500020)
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:24 +0x2b
created by main.main
	/Users/mafredri/Golang/src/github.com/opennota/sigint_issue/main.go:22 +0xfe

rax    0x17
rbx    0x418a960
rcx    0x4055fe5
rdx    0x0
rdi    0x2
rsi    0x4107df8
rbp    0xc420009ab0
rsp    0xc420006600
r8     0xc420009f48
r9     0x4500000
r10    0x0
r11    0x202
r12    0x0
r13    0xf1
r14    0x11
r15    0x0
rip    0x4052ab2
rflags 0x202
cs     0x2b
fs     0x0
gs     0x0

@ianlancetaylor
Copy link
Member

It's because your C code calls the standard library system function. The system function sets SIGINT (and SIGQUIT) to be ignored while the program is executing. If the ^C delivers a SIGINT during that time, then the child process will be killed but the parent process--the Go program--will continue executing and will never see the SIGINT.

Closing because there is nothing we can do to fix this in Go.

@golang golang locked and limited conversation to collaborators Sep 17, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants