improve error messages when attached modules fail on startup
Change-Id: Ic1d2d77de2574043749ddbc00def48a6fe77b2bd
This commit is contained in:
@@ -342,6 +342,7 @@ class Module(HasAccessibles):
|
||||
self.attachedModules = {}
|
||||
self.errors = []
|
||||
self._isinitialized = False
|
||||
self._initfailed = False
|
||||
self.updateCallback = srv.dispatcher.announce_update
|
||||
|
||||
# handle module properties
|
||||
@@ -612,6 +613,7 @@ class Module(HasAccessibles):
|
||||
"""
|
||||
# we do not need self.errors any longer. should we delete it?
|
||||
# del self.errors
|
||||
self.polledModules = [m for m in self.polledModules if not m._initfailed]
|
||||
if self.polledModules:
|
||||
self.__poller = mkthread(self.__pollThread, self.polledModules, start_events.get_trigger())
|
||||
self.startModuleDone = True
|
||||
@@ -723,8 +725,10 @@ class Module(HasAccessibles):
|
||||
rfunc = getattr(mobj, 'read_' + pname)
|
||||
if rfunc.poll:
|
||||
pinfo.polled_parameters.append((mobj, rfunc, pobj))
|
||||
while True:
|
||||
try:
|
||||
for mobj in list(self.modules):
|
||||
if mobj._initfailed:
|
||||
modules.remove(mobj)
|
||||
for mobj in modules:
|
||||
# TODO when needed: here we might add a call to a method :meth:`beforeWriteInit`
|
||||
mobj.writeInitParams()
|
||||
@@ -734,7 +738,6 @@ class Module(HasAccessibles):
|
||||
for mobj, rfunc, _ in m.pollInfo.polled_parameters:
|
||||
mobj.callPollFunc(rfunc, raise_com_failed=True)
|
||||
# TODO when needed: here we might add calls to a method :meth:`afterInitPolls`
|
||||
break
|
||||
except CommunicationFailedError as e:
|
||||
# when communication failed, probably all parameters and may be more modules are affected.
|
||||
# as this would take a lot of time (summed up timeouts), we do not continue
|
||||
@@ -743,8 +746,6 @@ class Module(HasAccessibles):
|
||||
self.log.error('communication failure on startup: %s', e)
|
||||
started_callback()
|
||||
started_callback = None
|
||||
self.triggerPoll.wait(0.1) # wait for reconnection or max 10 sec.
|
||||
break
|
||||
if started_callback:
|
||||
started_callback()
|
||||
if not polled_modules: # no polls needed - exit thread
|
||||
|
||||
@@ -30,6 +30,10 @@ from frappy.version import get_version
|
||||
from frappy.modules import Module
|
||||
|
||||
|
||||
class InitFailed(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SecNode:
|
||||
"""Managing the modules.
|
||||
|
||||
@@ -85,11 +89,15 @@ class SecNode:
|
||||
if not modobj.initModuleDone:
|
||||
self.errors.append(f'{modobj.initModule.__qualname__} was not '
|
||||
f'called, probably missing super call')
|
||||
except InitFailed:
|
||||
raise
|
||||
except Exception as e:
|
||||
if self.traceback_counter == 0:
|
||||
self.log.exception(traceback.format_exc())
|
||||
self.traceback_counter += 1
|
||||
self.errors.append(f'error initializing {modulename}: {e!r}')
|
||||
modobj._initfailed = True
|
||||
raise InitFailed('try to access erroneous module')
|
||||
modobj._isinitialized = True
|
||||
self.log.debug('initialized module %r', modulename)
|
||||
return modobj
|
||||
@@ -101,8 +109,11 @@ class SecNode:
|
||||
When creating a new module, srv.module_config is accessed to get the
|
||||
modules configuration.
|
||||
"""
|
||||
if modulename in self.modules:
|
||||
return self.modules[modulename]
|
||||
modobj = self.modules.get(modulename)
|
||||
if modobj:
|
||||
if modobj._initfailed:
|
||||
raise InitFailed('try to access erroneous module')
|
||||
return modobj
|
||||
if modulename in list(self.modules.values()):
|
||||
# it's actually already the module object
|
||||
return modulename
|
||||
@@ -205,8 +216,11 @@ class SecNode:
|
||||
def build_descriptive_data(self):
|
||||
modules = {}
|
||||
result = {'modules': modules}
|
||||
for modulename in self.modules:
|
||||
for modulename in list(self.modules):
|
||||
try:
|
||||
modobj = self.get_module(modulename)
|
||||
except InitFailed:
|
||||
continue
|
||||
if not modobj.export:
|
||||
continue
|
||||
# some of these need rework !
|
||||
|
||||
Reference in New Issue
Block a user