-
Notifications
You must be signed in to change notification settings - Fork 18k
runtime: panicmem should expose the address it's panicking about. #37023
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
Comments
We could do something about this. The types of runtime panics are explicitly unspecified: https://golang.org/ref/spec#Run_time_panics
Should we include kind-of also? Not sure. We can rapidly reach implementation-specific areas, which I don't think we want to do. |
You can't always get the address either. For example on amd64 if you fault because the address is malformed (top 17 bits not all 0s or all 1s) then you don't get the address in the fault at all. In that case it definitely can't be passed anywhere else. I am not convinced we should do this. Why do you want it? There's not usually much use to it. |
Yeah, I noticed the lack of address with high bits set recently. I remember all the mc68k programs that said "oh hey the address bus is only 24 bits, we can use that top word and just mask it out", and I am so looking forward to having that again in amd64 in a little bit here. The reason I want it is that it turns out to let me distinguish between "i have no idea what garbage was here" and "wow what an amazing coincidence that address is in a space that got munmapped recently". So if I get a throw(), I can only dump every mmap operation as it happens just in case there's a crash later, and then after a week of logging, I get a crash in which the relevant thing is in the last five lines of the logs. If I use PanicOnFault, I can't tell which of the things are relevant, but I can look at recent activity. If I used PanicOnFault, and got the address (when possible/applicable), I could look at the recent activity and report exactly what happened, and life would be a lot simpler. (And it really does seem to be days-to-weeks between events.) I agree that there's not usually much use to it, but in the specific case where mmap is involved (which is pretty much the only time I'd be likely to want PanicOnFault anyway), the distinction between "an invalid address" and "an invalid address which I can trace to a specific memory-mapped region" is very significant. |
Adding just the address does help with PanicOnFault, so I could see maybe doing this. |
I don't see a problem as long as we document that the information is system-dependent, and is not always available or reliable. Would this be a language spec change or just a runtime package change? The spec says that runtime errors have "perhaps other methods" so I guess we can just do it in the runtime. There are three signals that produce a runtime panic: |
Intuitively, I would be really confused if a runtime panic from SIGFPE gave me a different kind of address than the other two do, and it's redundant with the already-available stack backtrace. So I think it'd probably be more confusing than not to provide that one. (If SIGFPE gave the address of the floating point object, that might almost be useful, but not very because if you know what code is executing, you're already able to narrow it down pretty well.) I don't think it makes sense to add a spec change, because this is so specific to a particular runtime implementation; if you don't have runtime.PanicOnFault, it'll never come up. |
SIGFPE is already turning into a different panic. Based on the discussion, it seems like this is a likely accept. |
No change in consensus, so accepting. |
Change https://golang.org/cl/249677 mentions this issue: |
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:
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):
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.)
The text was updated successfully, but these errors were encountered: