fixed unhandled panic and wrapped all internal goroutines
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package routine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"sync"
|
||||
@@ -33,3 +34,17 @@ func FireAndForget(f func(), wg ...*sync.WaitGroup) {
|
||||
f()
|
||||
}()
|
||||
}
|
||||
|
||||
// SafeWrap wraps the provided function with auto panic recover handling
|
||||
// and returns any eventual panic as regular error.
|
||||
func SafeWrap(f func() error) func() error {
|
||||
return func() (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = fmt.Errorf("[SafeWrap] recovered from panic: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package routine_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -12,7 +13,7 @@ func TestFireAndForget(t *testing.T) {
|
||||
|
||||
fn := func() {
|
||||
called = true
|
||||
panic("test")
|
||||
panic("test_recover")
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
@@ -22,6 +23,29 @@ func TestFireAndForget(t *testing.T) {
|
||||
wg.Wait()
|
||||
|
||||
if !called {
|
||||
t.Error("Expected fn to be called.")
|
||||
t.Fatal("Expected fn to be called.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSafeWrap(t *testing.T) {
|
||||
called := false
|
||||
|
||||
fn := func() error {
|
||||
called = true
|
||||
panic("test_recover")
|
||||
}
|
||||
|
||||
err := routine.SafeWrap(fn)()
|
||||
|
||||
if !called {
|
||||
t.Fatal("Expected fn to be called.")
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected fn panic to be converted to error")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "test_recover") {
|
||||
t.Fatal("Expected the returned error to contain the recovered panic value")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user