Description
Go version
go version go1.22.4 linux/amd64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/ronanj/.cache/go-build'
GOENV='/home/ronanj/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/ronanj/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ronanj/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.4'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build4169732472=/tmp/go-build -gno-record-gcc-switches'
What did you do?
The following program will generate a fatal error: concurrent map writes
package main
import (
"runtime/debug"
"time"
)
var l = map[nt]int{}
func worker() {
for {
l[1] = 0
}
}
func main() {
debug.SetTraceback("all")
go worker()
go worker()
for {
time.Sleep(time.Second)
}
}
Run it with go run
$go build -o test test.go
$./test
fatal error: concurrent map writes
goroutine 6 gp=0xc000007500 m=2 mp=0xc000048808 [running]:
runtime.fatal({0x47c06b?, 0x0?})
/usr/local/go/src/runtime/panic.go:1042 +0x5c fp=0xc000044f78 sp=0xc000044f48 pc=0x430fdc
runtime.mapassign_fast64(0x46e140, 0xc000072090, 0x1)
/usr/local/go/src/runtime/map_fast64.go:102 +0x4d fp=0xc000044fb8 sp=0xc000044f78 pc=0x40ed2d
main.worker()
/tmp/test.go:12 +0x26 fp=0xc000044fe0 sp=0xc000044fb8 pc=0x4654e6
runtime.goexit({})
/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc000044fe8 sp=0xc000044fe0 pc=0x45f101
created by main.main in goroutine 1
/tmp/test.go:18 +0x2b
goroutine 1 gp=0xc0000061c0 m=nil [sleep]:
runtime.gopark(0x1bdc37393cd958?, 0xc000042700?, 0x40?, 0xd4?, 0x480f28?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0000426f0 sp=0xc0000426d0 pc=0x433dee
time.Sleep(0x3b9aca00)
/usr/local/go/src/runtime/time.go:195 +0x115 fp=0xc000042730 sp=0xc0000426f0 pc=0x45c395
main.main()
/tmp/test.go:21 +0x45 fp=0xc000042750 sp=0xc000042730 pc=0x465545
runtime.main()
/usr/local/go/src/runtime/proc.go:271 +0x29d fp=0xc0000427e0 sp=0xc000042750 pc=0x4339bd
runtime.goexit({})
/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0000427e8 sp=0xc0000427e0 pc=0x45f101```
...
Now run it with elevated privileges
$ go build -o test test.go
$ sudo setcap CAP_NET_BIND_SERVICE+eip ./test
$ ./test
fatal error: concurrent map writes
Stack traces are gone.
What did you see happen?
A stack trace
What did you expect to see?
Referring to #60272, I expected the traces to be shown when using debug.SetTraceback("all")
. But this solution only works for panic
errors, and does not for fatal
errors thrown internally from the go runtime (especially the map implementation).
Referring to the internal go runtime panic.go, it is mentioned that fatal does not include runtime frames, system goroutines, or frame metadata (fp, sp, pc) in the stack trace unless GOTRACEBACK=system or higher. Setting SetTraceback
to system
does not work either, as traces are also swallowed.
This issue, related to the change #60272 , is because the fatal
function only checks for isSecureMode
, while the panic
function checks the gotraceback
value before dumping the stack trace.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status