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._subscriptions = {}
self._lock = threading.RLock() self._lock = threading.RLock()
self.restart = srv.restart self.restart = srv.restart
self.shutdown = srv.shutdown
def broadcast_event(self, msg, reallyall=False): def broadcast_event(self, msg, reallyall=False):
"""broadcasts a msg to all active connections """broadcasts a msg to all active connections

View File

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