go: dl/internal/version, dl/gotip: corrupted output on SIGQUIT

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

$ go version
go version devel +866920a Sat Feb 1 06:01:05 2020 +0000 linux/amd64

Does this issue reproduce with the latest release?

1.13.7, no. Tip, yes.

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jake/nobackup/gotip_home/cache"
GOENV="/home/jake/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/jake/nobackup/gotip_home/gopath"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/jake/sdk/gotip"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/jake/sdk/gotip/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/jake/testproj/badquit/go.mod"
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-build408391790=/tmp/go-build -gno-record-gcc-switches"
GOROOT/bin/go version: go version devel +866920a Sat Feb 1 06:01:05 2020 +0000 linux/amd64
GOROOT/bin/go tool compile -V: compile version devel +866920a Sat Feb 1 06:01:05 2020 +0000
uname -sr: Linux 5.5.0-1-mainline
/usr/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.30.

What did you do?

Ran code that blocked, like:

package main

import "time"

func main() {
	time.Sleep(time.Hour)
}

Then, hit Ctrl+\ to send SIGQUIT.

What did you expect to see?

“Good” output with a back trace, register contents, etc. On 1.13.7, that’s:

^\SIGQUIT: quit
PC=0x44f053 m=0 sigcode=128

goroutine 5 [syscall]:
runtime.notetsleepg(0x4d4420, 0x34630b87115, 0x0)
	/usr/lib/go/src/runtime/lock_futex.go:227 +0x34 fp=0xc000034760 sp=0xc000034730 pc=0x409604
runtime.timerproc(0x4d4400)
	/usr/lib/go/src/runtime/time.go:311 +0x2f1 fp=0xc0000347d8 sp=0xc000034760 pc=0x43edc1
runtime.goexit()
	/usr/lib/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc0000347e0 sp=0xc0000347d8 pc=0x44d151
created by runtime.(*timersBucket).addtimerLocked
	/usr/lib/go/src/runtime/time.go:169 +0x10e

goroutine 1 [sleep]:
runtime.goparkunlock(...)
	/usr/lib/go/src/runtime/proc.go:310
time.Sleep(0x34630b8a000)
	/usr/lib/go/src/runtime/time.go:105 +0x157
main.main()
	/home/jake/testproj/badquit/main.go:6 +0x30

rax    0xfffffffffffffffc
rbx    0x3b9a9b15
rcx    0x44f053
rdx    0x0
rdi    0x4d4420
rsi    0x80
rbp    0xc0000346e8
rsp    0xc0000346a0
r8     0x0
r9     0x0
r10    0xc0000346d8
r11    0x202
r12    0xff
r13    0x1ffffffffffffff
r14    0x488494
r15    0x39
rip    0x44f053
rflags 0x202
cs     0x33
fs     0x0
gs     0x0
exit status 2

What did you see instead?

The output is broken very broken, as though it’s being output twice simultaneously.

^\SIGQUIT: quitSIGQUIT: quit

PC=PC=0x456e600x489f38 m= m=00 sigcode= sigcode=128128



goroutine goroutine 01 [ [idlesyscall]:
]:
runtime.epollwait(0x3, 0x7ffeea76fe10, syscall.Syscall60x36ee7f00000080(, 0xf70x0, , 0x10x36ee7f, , 0xcce30x0, , 0xc000040c500x0, , 0x10000040x0, , 0x00x0, , 0x00x0, , ...0xc000040c90)
, 	0x4948ec/home/jake/sdk/gotip/src/runtime/sys_linux_amd64.s, :0xc000098040705)
 +	0x20/usr/lib/go/src/syscall/asm_linux_amd64.s
:44runtime.netpoll +(0x50x34630b87429 fp=, 0xc000040c000xe0a18b77d01 sp=)
0xc000040bf8	 pc=/home/jake/sdk/gotip/src/runtime/netpoll_epoll.go0x489f15:
119 +os.(*Process).blockUntilWaitable0x92(
0xc000092060, 0x33, 0xcc4316c500020300runtime.findrunnable, (0x30xc000022800)
, 0x0	)
/usr/lib/go/src/os/wait_waitid.go	:/home/jake/sdk/gotip/src/runtime/proc.go31:2323 + +0x72b0x98
 fp=0xc000040cf0runtime.schedule( sp=)
0xc000040c00	/home/jake/sdk/gotip/src/runtime/proc.go pc=:0x497d582520
os.(*Process).wait +0x2fc(
0xc000092060runtime.park_m, (0x4f3c200xc000000180, 0x4f3c28)
, 	0x4f3c18/home/jake/sdk/gotip/src/runtime/proc.go)
:2690	 +/usr/lib/go/src/os/exec_unix.go0x9d:
22 +0x39 fp=runtime.mcall0xc000040d68( sp=0x00xc000040cf0)
 pc=	/home/jake/sdk/gotip/src/runtime/asm_amd64.s:0x4952e9318
 +0x5bos.(*Process).Wait
(...)

	goroutine /usr/lib/go/src/os/exec.go1: [125sleep
]:
os/exec.(*Cmd).Wait(time.Sleep0xc0000a0000(, 0x34630b8a0000x0)
, 	0x0/home/jake/sdk/gotip/src/runtime/time.go)
:	198/usr/lib/go/src/os/exec/exec.go +:0xba501
 +main.main0x60( fp=)
0xc000040de0	 sp=/home/jake/testproj/badquit/main.go0xc000040d68: pc=60x4aa710 +
0x30os/exec.(*Cmd).Run
(
0xc0000a0000rax    , 0xfffffffffffffffc0xc000089c00
, rbx    0x340x36ee7f)

	rcx    /usr/lib/go/src/os/exec/exec.go0x456e60:
341rdx     +0x800x5c
 fp=rdi    0xc000040e080x3 sp=
0xc000040de0rsi     pc=0x7ffeea76fe100x4a9bac

rbp    0x7ffeea770410main.main
(rsp    )
0x7ffeea76fdc0	
/home/jake/go/pkg/mod/golang.org/dl@v0.0.0-20200128181350-716300cef114/gotip/main.gor8     :0x059
 +r9     0x5120x0 fp=
0xc000040f60r10     sp=0x36ee7f0xc000040e08
 pc=r11    0x4ad7b20x246

r12    runtime.main0x3
(r13    )
0x4dd640	
/usr/lib/go/src/runtime/proc.gor14    :0x48bba9203
 +r15    0x21e0x0 fp=
0xc000040fe0rip     sp=0x456e600xc000040f60
 pc=rflags 0x42d87e0x246

runtime.goexitcs     (0x33)

	fs     /usr/lib/go/src/runtime/asm_amd64.s0x0:
1357gs      +0x00x1
 fp=0xc000040fe8 sp=0xc000040fe0 pc=0x457851

rax    0xf7
rbx    0xc000024500
rcx    0x489f3a
rdx    0xc000040c50
rdi    0x1
rsi    0xcce3
rbp    0xc000040ce0
rsp    0xc000040bf8
r8     0x0
r9     0x0
r10    0x1000004
r11    0x216
r12    0xffffffffffffffff
r13    0x3
r14    0x2
r15    0xaa
rip    0x489f38
rflags 0x216
cs     0x33
fs     0x0
gs     0x0
exit status 2

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (15 by maintainers)

Most upvoted comments

go run (and the go command in general) traps SIGQUIT (see here and here) so it doesn’t go the runtime and cause a traceback in the go process itself.

You’re right that the dl binaries could do the same. It would require just a little code that’s different between UNIX/non-UNIX. Alternatively, as you point out, it could directly exec the go binary instead of using cmd.Run, which would take the dl binary out of the picture entirely. I’m pretty sure all platforms have syscall.Exec with the same signature, and it might even make the code simpler.

Indeed, my CL would fix both.

Great, thank you.

I’d also submit something to deduplicate those two a bit (since they have copies of the same helpers), but that’s perhaps a different issue. 😄

Please file a separate issue for that.