Improve and fix module startup and shutdown procedures as well as error reporting

This commit is contained in:
Daniel 2019-10-09 16:35:33 +02:00
parent b0204f95ff
commit 2282c6bb71
5 changed files with 106 additions and 35 deletions

View file

@ -13,7 +13,7 @@ import (
)
var (
modulesLock sync.Mutex
modulesLock sync.RWMutex
modules = make(map[string]*Module)
// ErrCleanExit is returned by Start() when the program is interrupted before starting. This can happen for example, when using the "--help" flag.
@ -46,6 +46,10 @@ type Module struct {
microTaskCnt *int32
waitGroup sync.WaitGroup
// events
eventHooks map[string][]*eventHook
eventHooksLock sync.RWMutex
// dependency mgmt
depNames []string
depModules []*Module
@ -69,9 +73,9 @@ func (m *Module) shutdown() error {
// start shutdown function
m.waitGroup.Add(1)
stopFnError := make(chan error)
stopFnError := make(chan error, 1)
go func() {
stopFnError <- m.runModuleCtrlFn("stop module", m.stop)
stopFnError <- m.runCtrlFn("stop module", m.stop)
m.waitGroup.Done()
}()
@ -84,16 +88,8 @@ func (m *Module) shutdown() error {
// wait for results
select {
case err := <-stopFnError:
return err
case <-done:
select {
case err := <-stopFnError:
return err
default:
return nil
}
case <-time.After(3 * time.Second):
case <-time.After(30 * time.Second):
log.Warningf(
"%s: timed out while waiting for workers/tasks to finish: workers=%d tasks=%d microtasks=%d, continuing shutdown...",
m.Name,
@ -102,11 +98,18 @@ func (m *Module) shutdown() error {
atomic.LoadInt32(m.microTaskCnt),
)
}
return nil
}
func dummyAction() error {
return nil
// collect error
select {
case err := <-stopFnError:
return err
default:
log.Warningf(
"%s: timed out while waiting for stop function to finish, continuing shutdown...",
m.Name,
)
return nil
}
}
// Register registers a new module. The control functions `prep`, `start` and `stop` are technically optional. `stop` is called _after_ all added module workers finished.
@ -141,20 +144,10 @@ func initNewModule(name string, prep, start, stop func() error, dependencies ...
prep: prep,
start: start,
stop: stop,
eventHooks: make(map[string][]*eventHook),
depNames: dependencies,
}
// replace nil arguments with dummy action
if newModule.prep == nil {
newModule.prep = dummyAction
}
if newModule.start == nil {
newModule.start = dummyAction
}
if newModule.stop == nil {
newModule.stop = dummyAction
}
return newModule
}