diff options
| author | Keith Randall <khr@golang.org> | 2025-11-05 18:05:42 -0800 |
|---|---|---|
| committer | David Chase <drchase@google.com> | 2025-11-06 05:00:27 -0800 |
| commit | 48c7fa13c63761c8b52cbfac1f9eab062d475c0c (patch) | |
| tree | 14eca1749ddb9132aa3153054841d5037154396d /src/runtime/panic.go | |
| parent | 8111104a2120e14ef068b9cfbda91965473ab345 (diff) | |
| download | go-48c7fa13c63761c8b52cbfac1f9eab062d475c0c.tar.xz | |
Revert "runtime: remove the pc field of _defer struct"
This reverts commit 361d51a6b58bccaab0559e06737c918018a7a5fa.
Reason for revert: Breaks some tests inside Google (on arm64?)
Change-Id: Iaea45fdcf9b4f9d36553687ca7f479750fe559da
Reviewed-on: https://go-review.googlesource.com/c/go/+/718066
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Youlin Feng <fengyoulin@live.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/runtime/panic.go')
| -rw-r--r-- | src/runtime/panic.go | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go index ded85feffa..325bf74aa8 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -354,6 +354,7 @@ func deferproc(fn func()) { d.link = gp._defer gp._defer = d d.fn = fn + d.pc = sys.GetCallerPC() // We must not be preempted between calling GetCallerSP and // storing it to d.sp because GetCallerSP's result is a // uintptr stack pointer. @@ -457,6 +458,7 @@ func deferrangefunc() any { d := newdefer() d.link = gp._defer gp._defer = d + d.pc = sys.GetCallerPC() // We must not be preempted between calling GetCallerSP and // storing it to d.sp because GetCallerSP's result is a // uintptr stack pointer. @@ -516,6 +518,7 @@ func deferconvert(d0 *_defer) { } for d1 := d; ; d1 = d1.link { d1.sp = d0.sp + d1.pc = d0.pc if d1.link == nil { d1.link = tail break @@ -544,6 +547,7 @@ func deferprocStack(d *_defer) { d.heap = false d.rangefunc = false d.sp = sys.GetCallerSP() + d.pc = sys.GetCallerPC() // The lines below implement: // d.link = gp._defer // d.head = nil @@ -971,6 +975,8 @@ func (p *_panic) nextDefer() (func(), bool) { fn := d.fn + p.retpc = d.pc + // Unlink and free. popDefer(gp) @@ -1010,12 +1016,6 @@ func (p *_panic) nextFrame() (ok bool) { // it's non-zero. if u.frame.sp == limit { - f := u.frame.fn - if f.deferreturn == 0 { - throw("no deferreturn") - } - p.retpc = f.entry() + uintptr(f.deferreturn) - break // found a frame with linked defers } @@ -1271,6 +1271,15 @@ func recovery(gp *g) { pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp) p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 0 + // The linker records the f-relative address of a call to deferreturn in f's funcInfo. + // Assuming a "normal" call to recover() inside one of f's deferred functions + // invoked for a panic, that is the desired PC for exiting f. + f := findfunc(pc) + if f.deferreturn == 0 { + throw("no deferreturn") + } + gotoPc := f.entry() + uintptr(f.deferreturn) + // Unwind the panic stack. for ; p != nil && uintptr(p.startSP) < sp; p = p.link { // Don't allow jumping past a pending Goexit. @@ -1293,7 +1302,7 @@ func recovery(gp *g) { // With how subtle defer handling is, this might not actually be // worthwhile though. if p.goexit { - pc, sp = p.startPC, uintptr(p.startSP) + gotoPc, sp = p.startPC, uintptr(p.startSP) saveOpenDeferState = false // goexit is unwinding the stack anyway break } @@ -1356,7 +1365,7 @@ func recovery(gp *g) { // branch directly to the deferreturn gp.sched.sp = sp - gp.sched.pc = pc + gp.sched.pc = gotoPc gp.sched.lr = 0 // Restore the bp on platforms that support frame pointers. // N.B. It's fine to not set anything for platforms that don't |
