Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling panics in go routines

Tags:

recovery

go

panic

I understand that to handle panic recover is used. But the following block fails to recover when panic arises in go routine

func main() {
    done := make(chan int64)
    defer fmt.Println("Graceful End of program")
    defer func() {
     r := recover()
     if _, ok := r.(error); ok {
        fmt.Println("Recovered")
     }
    }()

    go handle(done)
    for {
        select{
        case <- done:
        return
        }
    } 
}

func handle(done chan int64) {
    var a *int64
    a = nil

    fmt.Println(*a)
    done <- *a
}

However following block is able to execute as expected

func main() {
    done := make(chan int64)
    defer fmt.Println("Graceful End of program")
    defer func() {
     r := recover()
     if _, ok := r.(error); ok {
        fmt.Println("Recovered")
     }
    }()

    handle(done)
    for {
        select{
        case <- done:
        return
        }
    } 
}

func handle(done chan int64) {
    var a *int64
    a = nil

    fmt.Println(*a)
    done <- *a
}

How to recover from panics that arise in go routines. Here is the link for playground : https://play.golang.org/p/lkvKUxMHjhi

like image 225
Mohit Jain Avatar asked May 18 '18 10:05

Mohit Jain


1 Answers

Recover only works when called from the same goroutine as the panic is called in. From the Go blog:

The process continues up the stack until all functions in the current goroutine have returned, at which point the program crashes

You would have to have a deferred recover within the goroutine.

https://blog.golang.org/defer-panic-and-recover

The docs / spec also includes the same :

While executing a function F, an explicit call to panic or a run-time panic terminates the execution of F. Any functions deferred by F are then executed as usual. Next, any deferred functions run by F's caller are run, and so on up to any deferred by the top-level function in the executing goroutine. At that point, the program is terminated and the error condition is reported, including the value of the argument to panic. This termination sequence is called panicking

https://golang.org/ref/spec#Handling_panics

like image 84
Andrew Avatar answered Oct 21 '22 10:10

Andrew