-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version
)?
1.13
Does this issue reproduce with the latest release?
probably
What operating system and processor architecture are you using (go env
)?
AMD64
What did you do?
I don't know, but it resulted in a segfault. :) But then I started experimenting with panic and recover, and discovered (somewhat to my surprise) that I can catch a SEGV's panic.
What did you expect to see?
A runtime error/exception/something that has comparable information to what I'd get if I didn't recover().
What did you see instead?
The string "invalid memory address or nil pointer dereference"
So, contrast:
unexpected fault address 0x7f84e68d6112
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0x7f84e68d6112 pc=0x5f17cb]
goroutine 992352 [running]:
runtime.throw(0xfab924, 0x5)
/usr/local/Cellar/go/1.13/libexec/src/runtime/panic.go:774 +0x72 fp=0xd5b852e7f8 sp=0xd5b852e7c8 pc=0x42f3b2
runtime.sigpanic()
/usr/local/Cellar/go/1.13/libexec/src/runtime/signal_unix.go:401 +0x3de fp=0xd5b852e828 sp=0xd5b852e7f8 pc=0x444a3e
[...]
If I look at [runtime/]debug.StackTrace(), I can get some of this information, but I can't necessarily get the actual address of the unexpected fault. It looks to me like runtime has this information at the time when the panic is generated (or would be, if I turned on SetPanicOnFault):
case _SIGSEGV:
if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 {
panicmem()
}
// Support runtime/debug.SetPanicOnFault.
if g.paniconfault {
panicmem()
}
print("unexpected fault address ", hex(g.sigcode1), "\n")
throw("fault")
But it looks like panicmem doesn't expose these values. Possibly it should. I can't think of a reasonable approach immediately -- obviously I'd just like the siginfo_t exposed, except that this is unportable even by memory fault handling standards and won't be compatible between implementations. But it seems like exposing the affected address (g.sigcode1) and possibly the kind-of-error (SEGV_MAPERR or SEGV_ACCERR?)
But as a simple baseline that I think is probably supportable on current systems, if panicmem took a uintptr, and the resulting panic were an error type that could be queried for the uintptr, or displayed it by default, that might make life easier.
Because on the one hand, I want to catch the panics and prevent them from breaking things, but on the other hand, diagnosing them sort of benefits from having the address be available.
(On the third hand, it might be that changing the exact panic result in these cases would break the Compatibility Promise, without some hypothetical new debug.SetFancyPanicOnFault() that would not have been used in the existing code.)