3

What if an imported library spawns a goroutine that can panic? In this case, there is nothing a developer can do to stop the program from exiting.

Like in this code, calling a bad library with deferred recover does not help as the library is spawning a goroutine that panics, and it cannot be caught by the main's recover.

Do I understand it correct that the only remedy is to be very careful when choosing dependencies for one's project and hope that the authors do not do something similar?

package main

import (
    "fmt"
    "time"
)

func main() {
    defer func() {
        r := recover()
        if r != nil {
            fmt.Println("panic caught")
        }
    }()

    badLibrary()
}

func badLibrary() {
    go recklessFunction()
    time.Sleep(time.Second)
}

func recklessFunction() {
    panic("something went wrong")
}
IvanD
  • 2,728
  • 14
  • 26
  • 3
    Yes, that's why the general recommendation is to leave concurrency to the user of your library. – Volker Dec 30 '21 at 16:05
  • One way is to have your main go routine recover from any panic that may be raised by APIs you have no control over. – Margach Chris Dec 30 '21 at 17:51
  • 3
    @MargachChris The `main()` function cannot recover from panics happening on other goroutines. – icza Dec 30 '21 at 17:52
  • @icza Thank you for pointing this out but by "main", I meant the function on top on the call stack that would recover from the panic and not to allow the panic to propagate the ```main()``` function. – Margach Chris Dec 30 '21 at 20:08
  • @MargachChris Yes, but the question is about this happening in a 3rd party lib, where the asker has "no authority". – icza Dec 30 '21 at 20:48
  • 1
    See also: [Handling panics in go routines](https://stackoverflow.com/questions/50409011/handling-panics-in-go-routines) – blackgreen Dec 30 '21 at 20:57

1 Answers1

5

You're right, you can't do anything about that. Neither can you if a dependency calls os.Exit() for example.

Launching goroutines as a library is often bad practice anyway, let the client (user of the library) choose if concurrent execution (a goroutine) is wanted, adding the go keyword is trivial. There are exceptions of course.

icza
  • 389,944
  • 63
  • 907
  • 827