"defer recover( )" can not recover a panic.

262 views
Skip to first unread message

Fannie Zhang

unread,
Dec 10, 2021, 3:13:13 AM12/10/21
to golang-dev

Hi all,

 

In the following case, recover() cannot recover a panic.

playground: https://go.dev/play/p/cPkUZb6mbmt

 

package main

 

import "fmt"

 

func main() {

  d := div(1, 0)

  fmt.Println("Returned from div(): ", d)

}

 

func div(a, b int64) int64 {

  defer recover()

  if b == 0 {

    panic("integer divide by zero")

  }

  return a/b

}

 

 

The gorecover() function (below) checks whether argp is equal to p.argp, if they match, the caller is the one who can recover.

 

func gorecover(argp uintptr) interface{} {

                gp := getg()

                p := gp._panic

                if p != nil && !p.goexit && !p.recovered && argp == uintptr(p.argp) {

                                p.recovered = true

                                return p.arg

                }

                return nil

}

 

But for the above case, argp = div()’arpg = main()’sp +8, p.argp = gopanic()’argp = div()’sp + 8. They are not equal, causing gorecover to fail to recover and return nil.

Of course, I know the rationality and necessity of this check, but from my understanding of the above case, the recover in div deferred function should be able to recover the panic that occurred in the div?

What do you think?

If you think it should be able to recover, then in this case, the argp passed to gorecover should be recover()'argp, which is div()'sp+8.

 

Thanks & Best regards,

Fannie Zhang

 

 

Jan Mercl

unread,
Dec 10, 2021, 3:43:08 AM12/10/21
to Fannie Zhang, golang-dev
On Fri, Dec 10, 2021 at 9:13 AM Fannie Zhang <Fannie...@arm.com> wrote:

> In the following case, recover() cannot recover a panic.

Because the specs say the recover() works iff called in a deferred
function: https://go.dev/play/p/e-YxlmwC7gl

Fannie...@arm.com

unread,
Dec 10, 2021, 5:54:11 AM12/10/21
to golang-dev
So you mean that "defer recover()" is not that recover is not in the deferred function? But this case https://go.dev/play/p/CH9GkpGFbPd works. I think that these two examples are quite similar. 

Thank you,
Fannie

Jan Mercl

unread,
Dec 10, 2021, 6:03:20 AM12/10/21
to Fannie...@arm.com, golang-dev
On Fri, Dec 10, 2021 at 11:54 AM Fannie...@arm.com <Fannie...@arm.com> wrote:

> So you mean that "defer recover()" is not that recover is not in the deferred function? But this case https://go.dev/play/p/CH9GkpGFbPd works. I think that these two examples are quite similar.

They are substantially different. In this new example recover() _is_
called in a deferred function. That's why it now works.

Exactly as the specs say.

Fannie...@arm.com

unread,
Dec 12, 2021, 8:26:57 PM12/12/21
to golang-dev
Ok, I got it. I misunderstood the defer function. Thank you for your explanation.

Fannie

Reply all
Reply to author
Forward
0 new messages