Routine manager now recovers from panicking goroutines
This commit is contained in:
parent
3cd53b3dd9
commit
92b645f34c
@ -6,6 +6,7 @@ import "fmt"
|
|||||||
import "log"
|
import "log"
|
||||||
import "time"
|
import "time"
|
||||||
import "sync"
|
import "sync"
|
||||||
|
import "errors"
|
||||||
|
|
||||||
type routine struct {
|
type routine struct {
|
||||||
run, shutdown func () error
|
run, shutdown func () error
|
||||||
@ -71,17 +72,16 @@ type Manager struct {
|
|||||||
// Run returns only when all routines have exited.
|
// Run returns only when all routines have exited.
|
||||||
func (manager *Manager) Run () error {
|
func (manager *Manager) Run () error {
|
||||||
var waitGroup sync.WaitGroup
|
var waitGroup sync.WaitGroup
|
||||||
var errExit error
|
|
||||||
|
|
||||||
for _, routine := range manager.Routines {
|
for _, routine := range manager.Routines {
|
||||||
if routine != nil {
|
if routine != nil {
|
||||||
waitGroup.Add(1)
|
waitGroup.Add(1)
|
||||||
go manager.runRoutine(routine, &waitGroup, &errExit)
|
go manager.runRoutine(routine, &waitGroup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waitGroup.Wait()
|
waitGroup.Wait()
|
||||||
return errExit
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown shuts down all routines in the manager.
|
// Shutdown shuts down all routines in the manager.
|
||||||
@ -113,21 +113,26 @@ func (manager *Manager) log (message ...any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *Manager) runRoutine (routine Routine, group *sync.WaitGroup, errExit *error) {
|
func (manager *Manager) runRoutine (routine Routine, group *sync.WaitGroup) {
|
||||||
defer group.Done()
|
defer group.Done()
|
||||||
|
|
||||||
var err error
|
|
||||||
for {
|
for {
|
||||||
|
lastStart := time.Now()
|
||||||
|
err := panicWrap(routine.Run)
|
||||||
|
|
||||||
stopping := false
|
stopping := false
|
||||||
manager.stoppingMutex.Lock()
|
manager.stoppingMutex.Lock()
|
||||||
stopping = manager.stopping
|
stopping = manager.stopping
|
||||||
manager.stoppingMutex.Unlock()
|
manager.stoppingMutex.Unlock()
|
||||||
if stopping { break }
|
if stopping {
|
||||||
|
if err == nil {
|
||||||
// TODO: recover from panics
|
manager.log("(i) stopped routine")
|
||||||
lastStart := time.Now()
|
} else {
|
||||||
err = routine.Run()
|
manager.log("!!! stopped routine, with error:", err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
manager.log("(i) routine exited")
|
manager.log("(i) routine exited")
|
||||||
break
|
break
|
||||||
@ -142,8 +147,15 @@ func (manager *Manager) runRoutine (routine Routine, group *sync.WaitGroup, errE
|
|||||||
manager.log("(i) routine is being restarted")
|
manager.log("(i) routine is being restarted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err != nil {
|
|
||||||
*errExit = err
|
func panicWrap (f func () error) (err error) {
|
||||||
}
|
defer func () {
|
||||||
|
if pan := recover(); pan != nil {
|
||||||
|
err = errors.New(fmt.Sprint(pan))
|
||||||
|
}
|
||||||
|
} ()
|
||||||
|
|
||||||
|
err = f()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user