Are all runtime errors recoverable in Go?
Are there any examples where runtime errors will just crash the program without a recoverable panic?
For example, Go Out-Of-Memory (OOM) errors are not recoverable.
src/runtime/panic.go
:// fatalpanic implements an unrecoverable panic. It is like fatalthrow, except // that if msgs != nil, fatalpanic also prints panic messages and decrements // runningPanicDefers once main is blocked from exiting. func fatalpanic(msgs *_panic) { // ... } // fatalthrow implements an unrecoverable runtime throw. It freezes the // system, prints stack traces starting from its caller, and terminates the // process. func fatalthrow() { // ... }
First change your errorHandler()
because if there are no panics, r
will be nil
and thus the type assertion would fail:
func errorHandler() {
if r := recover(); r != nil {
fmt.Println(r)
}
}
And now here are some examples with code to produce unrecoverable runtime errors:
1. Out of memory:
func foo() {
defer errorHandler()
_ = make([]int64, 1<<40) // You have to change the size on 32-bit systems
}
2. Concurrent map writes and reads
For details see How to recover from concurrent map writes?, for example see Can marshalling a map[string]string to json return an error?
func foo() {
defer errorHandler()
m := map[string]int{}
go func() {
for {
m["x"] = 1
}
}()
for {
_ = m["x"]
}
}
3. Stack memory exhaustion
For details, see Does Go have an "infinite call stack" equivalent?
func foo() {
defer errorHandler()
var f func(a [1000]int64)
f = func(a [1000]int64) {
f(a)
}
f([1000]int64{})
}
4. Attempting to launch a nil
function as a goroutine
func foo() {
defer errorHandler()
var f func()
go f()
}
5. All goroutines are asleep - deadlock
Title says it all. Here's a simple code to block the current goroutine, but if you have launched other goroutines, you obviously won't experience the crash. See other examples here: Go project's main goroutine sleep forever?
func foo() {
defer errorHandler()
select {}
}
6. Thread limit exhaustion
If your goroutines get blocked by IO operations, new threads may be started to execute your other goroutines. There is obviously a limit to the max thread count, if it is reached, your app will crash.