-
Notifications
You must be signed in to change notification settings - Fork 18k
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
runtime: sigpanic can make dead pointer live again #27518
Comments
Accidentally clicked submit before I was done writing. Fixing this is messy. I'm planning on adding support for conservative stack frames for preemption, but we could use the same thing for the parent of a sigpanic frame. That could fix the stack scanning problem. But what if the defer grows the stack? That might still be okay combined with conservative scanning: stack copying will think x is live and will either update it (if it points to the stack), or not update it (if it points to the heap), but nothing can actually observe x, so both of these actions are harmless. |
Will stack tracing solve this? When it panics, the frame is essentially dead, except the variables captured by the defer closure, and the closure struct itself. Those variables are address-taken. If they are actually live in the defer closure, stack tracing will find them. The non-address-taken variables are not accessible, so we can treat them dead. So, we can just let stack tracing take care of it, without adjusting the PC? |
I don't think stack tracing will solve this. x points to heap-allocated memory. x itself doesn't have its address taken, so it is tracked using the old rules. It will certainly be collected at the GC at line 29, and be live again at the the point of the defer. |
Yes, this is what I was suggesting. We can treat all the non-address-taken variables dead (except the return values). So
If I understand correctly, for capture-by-value variables there is a copy of the value in the closure struct. So we don't need the original variable from the dead frame. |
Looking at this a bit more, this should work. One complication is that there are locals that are live after a panic: the PAUTOHEAP variables that point to return values that escape. The code that copies these values back into the return slots on the stack run after the defers (after deferreturn), so if the defer recovers those variables are needed. I think the right answer is to move the pc to the deferreturn call. That should have precisely the bitmap we need (args are dead, return values are live, except the ones which moved to the heap, in which case their PAUTOHEAP variables are live instead). |
I haven't checked, but doesn't this also include variables captured in deferred closures? If so, then if we panicked before all of the defers in the function were pushed, the liveness map at |
With stack tracing, we won't be including variables captured in deferred closures in the live map, because those are all captured by reference. Those variables will be stack objects and be tracked by pointer, so they only need to be initialized before their address is put in a closure. |
Sounds good. |
Change https://golang.org/cl/134637 mentions this issue: |
Change https://golang.org/cl/139898 mentions this issue: |
On wasm, pcln tables are indexed by "resumption point ID" instead of by pc offset. When finding a deferreturn call, we must find the associated resumption point ID for the deferreturn call. Update #27518 Fixes wasm bug introduced in CL 134637. Change-Id: I3d178a3f5203a06c0180a1aa2309bfb7f3014f0f Reviewed-on: https://go-review.googlesource.com/c/139898 Reviewed-by: Cherry Zhang <cherryyz@google.com>
Change https://golang.org/cl/190098 mentions this issue: |
What version of Go are you using (
go version
)?Demonstrated with Go 1.11, 1.10 and, 1.9. Doesn't reproduce with Go 1.8.
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?What did you do?
https://play.golang.org/p/2EdeQAVbZQK
What did you expect to see?
Nothing.
What did you see instead?
runtime: pointer 0xc00007a000 to unallocated span span.base()=0xc00007a000 span.limit=0xc00007c000 span.state=3
I knew there some something fishy about unwinding the PC back to the defer in the sigpanic parent frame. Fixing this is messy.
/cc @RLH @randall77 @ianlancetaylor
The text was updated successfully, but these errors were encountered: