You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
x := deferproc(...)
if x != 0 { goto deferreturn }
...
deferreturn:
deferreturn()
Normally deferproc returns 0. However, when a subsequent panic is caught and the defer is run by the panic, and that defer recovers, then the runtime arranges the defer to return 1 at the same deferproc callsite. The generated code then immediately jumps to deferreturn().
We should just make a recover'd panic return to the deferreturn callsite. That may involve passing the pc of the deferreturn call to deferproc.
It would mean stack traces during panic point to the end of the function instead of to the site of the defer call. That's arguably more correct (and matches the behavior on non-panic running of defers).
Part of the reason for this fix is that the code past deferproc() but before the branch gets executed twice in a defer/panic/recover scenario. The SSA backend has been known to insert non-idempotent code in spots like that (See #19201. That was for selectrecv not deferproc, but the same issue applies.)
The generated code may have originally been written this way because there was a push/pop sequence around the deferproc call, and the pops were required on the second return as well. Those push/pop sequences were removed a long time ago.
We currently compile a defer to this:
Normally deferproc returns 0. However, when a subsequent panic is caught and the defer is run by the panic, and that defer recovers, then the runtime arranges the defer to return 1 at the same deferproc callsite. The generated code then immediately jumps to deferreturn().
We should just make a recover'd panic return to the deferreturn callsite. That may involve passing the pc of the deferreturn call to deferproc.
It would mean stack traces during panic point to the end of the function instead of to the site of the defer call. That's arguably more correct (and matches the behavior on non-panic running of defers).
Part of the reason for this fix is that the code past deferproc() but before the branch gets executed twice in a defer/panic/recover scenario. The SSA backend has been known to insert non-idempotent code in spots like that (See #19201. That was for selectrecv not deferproc, but the same issue applies.)
The generated code may have originally been written this way because there was a push/pop sequence around the deferproc call, and the pops were required on the second return as well. Those push/pop sequences were removed a long time ago.
@rsc @mdempsky
See #19331
The text was updated successfully, but these errors were encountered: