improve more handling of errors when starting server

+ add shutdown method to server (and dispatcher)
This commit is contained in:
l_samenv 2021-04-08 10:21:44 +02:00
parent dec286460d
commit d3fc01689f
2 changed files with 33 additions and 16 deletions

View File

@ -82,6 +82,7 @@ class Dispatcher:
self._subscriptions = {}
self._lock = threading.RLock()
self.restart = srv.restart
self.shutdown = srv.shutdown
def broadcast_event(self, msg, reallyall=False):
"""broadcasts a msg to all active connections

View File

@ -29,6 +29,7 @@ import os
import sys
import threading
import time
import traceback
from collections import OrderedDict
from secop.errors import ConfigError, SECoPError
@ -219,6 +220,10 @@ class Server:
self._restart = True
self.interface.shutdown()
def shutdown(self):
self._restart = False
self.interface.shutdown()
def _processCfg(self):
errors = []
opts = dict(self.node_cfg)
@ -227,31 +232,39 @@ class Server:
if opts:
errors.append(self.unknown_options(cls, opts))
self.modules = OrderedDict()
badclass = None
failure_traceback = None # traceback for the last error
failed = set() # python modules failed to load
self.lastError = None
for modname, options in self.module_cfg.items():
opts = dict(options)
pymodule = None
try:
classname = opts.pop('class')
pymodule = classname.rpartition('.')[0]
if pymodule in failed:
continue
cls = get_class(classname)
modobj = cls(modname, self.log.getChild(modname), opts, self)
# all used args should be popped from opts!
if opts:
errors.append(self.unknown_options(cls, opts))
self.modules[modname] = modobj
except ConfigError as e:
errors.append(str(e))
except Exception as e:
if str(e) == 'no such class':
errors.append('%s not found' % classname)
if pymodule is None:
if str(e) == 'no such class':
errors.append('%s not found' % classname)
else:
raise
errors.append(repr(e))
else:
failed.add(pymodule)
badclass = classname
errors.append('error importing %s' % pymodule)
failure_traceback = traceback.format_exc()
errors.append('error importing %s' % classname)
else:
try:
modobj = cls(modname, self.log.getChild(modname), opts, self)
# all used args should be popped from opts!
if opts:
errors.append(self.unknown_options(cls, opts))
self.modules[modname] = modobj
except Exception as e:
failure_traceback = traceback.format_exc()
errors.append('error creating %s: %r' % (modname, e))
poll_table = dict()
# all objs created, now start them up and interconnect
@ -276,7 +289,11 @@ class Server:
# call init on each module after registering all
for modname, modobj in self.modules.items():
modobj.initModule()
try:
modobj.initModule()
except Exception as e:
failure_traceback = traceback.format_exc()
errors.append('error initializing %s: %r' % (modname, e))
if errors:
for errtxt in errors:
@ -285,9 +302,8 @@ class Server:
# print a list of config errors to stderr
sys.stderr.write('\n'.join(errors))
sys.stderr.write('\n')
if badclass:
# force stack trace for import of last erroneous module
get_class(badclass)
if failure_traceback:
sys.stderr.write(failure_traceback)
sys.exit(1)
if self._testonly: