I am confused about this part of runtime.gopanic
. Below is my test golang code and its plan9
compilation.
package main
func main() {
a := func() {
b := func() {
recover()
}
defer b()
}
defer a()
panic(1)
}
main.go:3 0x105a100 493b6610 cmp rsp, qword ptr [r14+0x10]
main.go:3 0x105a104 7651 jbe 0x105a157
=> main.go:3 0x105a106* 4883ec68 sub rsp, 0x68
main.go:3 0x105a10a 48896c2460 mov qword ptr [rsp+0x60], rbp
main.go:3 0x105a10f 488d6c2460 lea rbp, ptr [rsp+0x60]
main.go:4 0x105a114 488d0dc50e0100 lea rcx, ptr [rip+0x10ec5]
main.go:4 0x105a11b 48894c2458 mov qword ptr [rsp+0x58], rcx
main.go:10 0x105a120 48894c2428 mov qword ptr [rsp+0x28], rcx
main.go:10 0x105a125 488d442410 lea rax, ptr [rsp+0x10]
main.go:10 0x105a12a e89136fdff call $runtime.deferprocStack
main.go:10 0x105a12f 85c0 test eax, eax
main.go:10 0x105a131 7515 jnz 0x105a148
main.go:10 0x105a133 eb00 jmp 0x105a135
main.go:11 0x105a135 488d05043f0000 lea rax, ptr [rip+0x3f04]
main.go:11 0x105a13c 488d1d8d3a0100 lea rbx, ptr [rip+0x13a8d]
main.go:11 0x105a143 e83847fdff call $runtime.gopanic
main.go:10 0x105a148 e8533cfdff call $runtime.deferreturn
main.go:10 0x105a14d 488b6c2460 mov rbp, qword ptr [rsp+0x60]
main.go:10 0x105a152 4883c468 add rsp, 0x68
main.go:10 0x105a156 c3 ret
main.go:3 0x105a157 e8c4cfffff call $runtime.morestack_noctxt
.:0 0x105a15c eba2 jmp $main.main
In golang, defer
will call runtime.deferprocStack
, so that the current g._defer
should point to the innermost defer. panic
will call runtime.gopanic
.
In my test code, when calling runtime.gopanic
, the current g._defer.fn
is main.a
. Just like this:
g._defer = &_defer{ fn: `main.a`, link: nil }
So in panic.go:890, main.a()
will be executed, and in main.a
, another _defer
whose fn is main.a.b
will be g._defer pointed to, previous defer
will assign to this one's link
. Just like this:
g._defer = &_defer{ fn: `main.a.b`, link: &_defer{ fn: `main.a`, link: nil } }
Howerer, in panic.go:895, gp._defer != d
is still true. Am I overlooking something in the whole process?
I use dlv
to debug my code, my golang version is 1.20.1, my machine is 64-bit macOS 11.7.2, and the kernel version is Darwin 20.6.0.
I'd really like to know the reason, I'd really appreciate it if you could explain!
Appenix
Here's what I see when debug with dlv
.
Maybe not the same goroutine execute runtime.gopanic
and runtime.deferprocStack
during the whole process?