From 5027feb553811f2cd3bb9357def4f88ea0f1be9f Mon Sep 17 00:00:00 2001 From: James Lu Date: Wed, 11 Nov 2015 18:55:51 -0800 Subject: [PATCH] Don't crash when REHASH loads a config file that's invalid This was actually several bugs in one: - The sys.exit() call in loadConf should be... toggleable - loadConf printed errors but forgot to re-raise the actual exception it caught - The error reply in the REHASH command was passing the wrong arguments to irc.reply(), which would cause an error within an error when it ran --- conf.py | 9 ++++++--- plugins/commands.py | 44 +++++++++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/conf.py b/conf.py index 1d01490..2a6f89a 100644 --- a/conf.py +++ b/conf.py @@ -47,15 +47,18 @@ def validateConf(conf): conf['login']['password'] != "changeme", "You have not set the login details correctly!" return conf -def loadConf(fname): +def loadConf(fname, errors_fatal=True): """Loads a PyLink configuration file from the filename given.""" with open(fname, 'r') as f: try: conf = yaml.load(f) except Exception as e: print('ERROR: Failed to load config from %r: %s: %s' % (fname, type(e).__name__, e)) - sys.exit(4) - return conf + if errors_fatal: + sys.exit(4) + raise + else: + return conf if world.testing: conf = testconf diff --git a/plugins/commands.py b/plugins/commands.py index 0da896c..3afe540 100644 --- a/plugins/commands.py +++ b/plugins/commands.py @@ -175,30 +175,32 @@ def rehash(irc, source, args): old_conf = conf.conf.copy() fname = conf.fname try: - new_conf = conf.validateConf(conf.loadConf(fname)) + new_conf = conf.loadConf(fname, errors_fatal=False) except Exception as e: # Something went wrong, abort. log.exception("Error REHASH'ing config: ") - irc.reply("Error loading configuration file: %s: %s", type(e).__name__, e) + irc.reply("Error loading configuration file: %s: %s" % (type(e).__name__, e)) return - conf.conf = new_conf - for network, ircobj in world.networkobjects.copy().items(): - # Server was removed from the config file, disconnect them. - log.debug('(%s) rehash: checking if %r is in new conf still.', irc.name, network) - if network not in new_conf['servers']: - # Disable autoconnect first. - log.debug('(%s) rehash: removing connection to %r (removed from config).', irc.name, network) - ircobj.serverdata['autoconnect'] = -1 - ircobj.aborted.set() - del world.networkobjects[network] - else: - ircobj.conf = new_conf - ircobj.serverdata = new_conf['servers'][network] - for network, sdata in new_conf['servers'].items(): - # New server was added. Connect them if not already connected. - if network not in world.networkobjects: - proto = utils.getProtoModule(sdata['protocol']) - world.networkobjects[network] = classes.Irc(network, proto, new_conf) - irc.reply("Done.") + else: + new_conf = conf.validateConf(new_conf) + conf.conf = new_conf + for network, ircobj in world.networkobjects.copy().items(): + # Server was removed from the config file, disconnect them. + log.debug('(%s) rehash: checking if %r is in new conf still.', irc.name, network) + if network not in new_conf['servers']: + log.debug('(%s) rehash: removing connection to %r (removed from config).', irc.name, network) + # Disable autoconnect first. + ircobj.serverdata['autoconnect'] = -1 + ircobj.aborted.set() + del world.networkobjects[network] + else: + ircobj.conf = new_conf + ircobj.serverdata = new_conf['servers'][network] + for network, sdata in new_conf['servers'].items(): + # New server was added. Connect them if not already connected. + if network not in world.networkobjects: + proto = utils.getProtoModule(sdata['protocol']) + world.networkobjects[network] = classes.Irc(network, proto, new_conf) + irc.reply("Done.") loglevels = {'DEBUG': 10, 'INFO': 20, 'WARNING': 30, 'ERROR': 40, 'CRITICAL': 50} @utils.add_cmd