Skip to content

runtime: ReadMemStats crashes with segmentation violation #61158

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

Closed
brutalsavage opened this issue Jul 3, 2023 · 4 comments
Closed

runtime: ReadMemStats crashes with segmentation violation #61158

brutalsavage opened this issue Jul 3, 2023 · 4 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge
Milestone

Comments

@brutalsavage
Copy link

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

$ go version
go version devel go1.21-6260049fa2

Does this issue reproduce with the latest release?

Reproduces on the most recent developer release branch, can see the later go-playground link

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

go env Output
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/.cache/go-build'
GOENV='/home/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/goroot'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/goroot/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.21-6260049fa2'
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 -ffile-prefix-map=/tmp/go-build531354456=/tmp/go-build -gno-record-gcc-switches'

What did you do?

using runtime.ReadMemStats with nil pointer leads to segmentation fault without nice crash message

package main

import (
	"runtime"
)

func main() {
	runtime.ReadMemStats(nil)
}

go.dev link to reproduce.

What did you expect to see?

A runtime panic message (i.e. panic: runtime error: invalid memory address or nil pointer dereference)

What did you see instead?

SIGSEGV: segmentation violation
PC=0x428424 m=0 sigcode=1

goroutine 0 [idle]:
runtime.readmemstats_m(0x0)
	/usr/local/go-faketime/src/runtime/mstats.go:487 +0x2c4 fp=0x7fe24f106da0 sp=0x7fe24f1061f8 pc=0x428424
runtime.ReadMemStats.func1()
	/usr/local/go-faketime/src/runtime/mstats.go:353 +0x17 fp=0x7fe24f106db8 sp=0x7fe24f106da0 pc=0x428137
runtime.systemstack()
	/usr/local/go-faketime/src/runtime/asm_amd64.s:509 +0x4a fp=0x7fe24f106dc8 sp=0x7fe24f106db8 pc=0x454eea

goroutine 1 [running]:
runtime.systemstack_switch()
	/usr/local/go-faketime/src/runtime/asm_amd64.s:474 +0x8 fp=0xc00003e700 sp=0xc00003e6f0 pc=0x454e88
runtime.ReadMemStats(0x0)
	/usr/local/go-faketime/src/runtime/mstats.go:352 +0x47 fp=0xc00003e728 sp=0xc00003e700 pc=0x4280e7
main.main()
	/tmp/sandbox1424825241/prog.go:8 +0x15 fp=0xc00003e740 sp=0xc00003e728 pc=0x457ef5
runtime.main()
	/usr/local/go-faketime/src/runtime/proc.go:267 +0x2b2 fp=0xc00003e7e0 sp=0xc00003e740 pc=0x42f9d2
runtime.goexit()
	/usr/local/go-faketime/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00003e7e8 sp=0xc00003e7e0 pc=0x455281

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/local/go-faketime/src/runtime/proc.go:398 +0xce fp=0xc00003efa8 sp=0xc00003ef88 pc=0x42fe0e
runtime.goparkunlock(...)
	/usr/local/go-faketime/src/runtime/proc.go:404
runtime.forcegchelper()
	/usr/local/go-faketime/src/runtime/proc.go:322 +0xa5 fp=0xc00003efe0 sp=0xc00003efa8 pc=0x42fca5
runtime.goexit()
	/usr/local/go-faketime/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00003efe8 sp=0xc00003efe0 pc=0x455281
created by runtime.init.6 in goroutine 1
	/usr/local/go-faketime/src/runtime/proc.go:310 +0x1a

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/local/go-faketime/src/runtime/proc.go:398 +0xce fp=0xc00003f778 sp=0xc00003f758 pc=0x42fe0e
runtime.goparkunlock(...)
	/usr/local/go-faketime/src/runtime/proc.go:404
runtime.bgsweep(0x0?)
	/usr/local/go-faketime/src/runtime/mgcsweep.go:280 +0x94 fp=0xc00003f7c8 sp=0xc00003f778 pc=0x41c954
runtime.gcenable.func1()
	/usr/local/go-faketime/src/runtime/mgc.go:200 +0x25 fp=0xc00003f7e0 sp=0xc00003f7c8 pc=0x411d85
runtime.goexit()
	/usr/local/go-faketime/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00003f7e8 sp=0xc00003f7e0 pc=0x455281
created by runtime.gcenable in goroutine 1
	/usr/local/go-faketime/src/runtime/mgc.go:200 +0x66

goroutine 4 [GC scavenge wait]:
runtime.gopark(0xc00005e000?, 0x47d860?, 0x1?, 0x0?, 0xc000006d00?)
	/usr/local/go-faketime/src/runtime/proc.go:398 +0xce fp=0xc00003ff70 sp=0xc00003ff50 pc=0x42fe0e
runtime.goparkunlock(...)
	/usr/local/go-faketime/src/runtime/proc.go:404
runtime.(*scavengerState).park(0x4cae20)
	/usr/local/go-faketime/src/runtime/mgcscavenge.go:425 +0x49 fp=0xc00003ffa0 sp=0xc00003ff70 pc=0x41a1c9
runtime.bgscavenge(0x0?)
	/usr/local/go-faketime/src/runtime/mgcscavenge.go:653 +0x3c fp=0xc00003ffc8 sp=0xc00003ffa0 pc=0x41a71c
runtime.gcenable.func2()
	/usr/local/go-faketime/src/runtime/mgc.go:201 +0x25 fp=0xc00003ffe0 sp=0xc00003ffc8 pc=0x411d25
runtime.goexit()
	/usr/local/go-faketime/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00003ffe8 sp=0xc00003ffe0 pc=0x455281
created by runtime.gcenable in goroutine 1
	/usr/local/go-faketime/src/runtime/mgc.go:201 +0xa5

rax    0x400000
rbx    0x0
rcx    0x44000
rdx    0x15588
rdi    0x0
rsi    0x0
rbp    0x7fe24f106d90
rsp    0x7fe24f1061f8
r8     0x15588
r9     0x0
r10    0x37c000
r11    0x39dc10
r12    0x719c10
r13    0x4cb2a0
r14    0x4caec0
r15    0xa
rip    0x428424
rflags 0x10206
cs     0x33
fs     0x0
gs     0x0
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jul 3, 2023
@randall77
Copy link
Contributor

ReadMemStats has no other way to report an error, so it has to use a panic for that. This is how the stdlib works in situations like this. For example: https://go.dev/play/p/1_QJli64K6M .

The stack trace is a bit confusing, as there's a stack switch in there. Maybe we could have ReadMemStats do a quick nil check before stack switching, so it is obvious what is at the top of stack when the nil pointer dereference happens.

(Note that there is special code to hide unexported runtime frames from tracebacks. That code isn't relevant here because exported functions like ReadMemStats are excepted.)

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/507755 mentions this issue: runtime: have ReadMemStats do a nil check before switching stacks

@brutalsavage
Copy link
Author

Hi thanks for the response, sorry if I am misunderstanding you, but currently ReadMemStats doesn't panic, it just Segfaults without any special panic message. This is not like the other example in your go.dev link.

@randall77
Copy link
Contributor

That's a good point, the traceback is not a panic but an internal runtime error.
In any case, that CL mentioned above should fix it.

@randall77 randall77 added this to the Go1.21 milestone Jul 3, 2023
@randall77 randall77 self-assigned this Jul 3, 2023
bradfitz pushed a commit to tailscale/go that referenced this issue Jul 15, 2023
This gives the user a better stack trace experience. No need to
expose them to runtime.systemstack and friends.

Fixes golang#61158

Change-Id: I4f423f82e54b062773067c0ae64622e37cb3948b
Reviewed-on: https://go-review.googlesource.com/c/go/+/507755
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Michael Knyszek <[email protected]>
Run-TryBot: Keith Randall <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
@golang golang locked and limited conversation to collaborators Jul 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge
Projects
None yet
Development

No branches or pull requests

3 participants