improve more handling of errors when starting server
+ add shutdown method to server (and dispatcher)
This commit is contained in:
@ -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
|
||||||
|
@ -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:
|
||||||
|
Reference in New Issue
Block a user