Abhilash Raj pushed to branch master at GNU Mailman / Mailman Core
Commits: 757e940a by Abhilash Raj at 2022-01-29T04:38:27+00:00 Fix a bug where exception in plugin initialization can cause crash. - - - - - 4564222d by Abhilash Raj at 2022-01-29T04:38:27+00:00 Merge branch 'fix-500' into 'master' Fix a bug where exception in plugin initialization can cause crash. See merge request mailman/mailman!952 - - - - - 3 changed files: - src/mailman/core/initialize.py - src/mailman/docs/NEWS.rst - src/mailman/plugins/tests/test_plugins.py Changes: ===================================== src/mailman/core/initialize.py ===================================== @@ -130,6 +130,27 @@ def initialize_1(config_path=None): mailman.config.config.push('extra testing config', extra_cfg) +@public +def run_plugin_pre_hook(config): + """Run the plugin pre_hooks, if one fails, disable the offending plugin.""" + disabled_plugins = [] + for name in config.plugins: # pragma: nocover + plugin = config.plugins[name] + if hasattr(plugin, 'pre_hook'): + try: + plugin.pre_hook() + except Exception: # pragma: nocover + log = logging.getLogger('mailman.plugins') + log.exception('Plugin failed to run its pre_hook: "{}". ' + 'It will be disabled and its components ' + "won't be loaded.".format(name)) + disabled_plugins.append(name) + + if disabled_plugins: + for plugin in disabled_plugins: + del config.plugins[plugin] + + @public def initialize_2(debug=False, propagate_logs=None, testing=False): """Second initialization step. @@ -159,18 +180,7 @@ def initialize_2(debug=False, propagate_logs=None, testing=False): log.warning( 'The [mailman]pre_hook configuration value has been replaced ' "by the plugins infrastructure, and won't be called.") - # Run the plugin pre_hooks, if one fails, disable the offending plugin. - for name in config.plugins: # pragma: nocover - plugin = config.plugins[name] - if hasattr(plugin, 'pre_hook'): - try: - plugin.pre_hook() - except Exception: # pragma: nocover - log = logging.getLogger('mailman.plugins') - log.exception('Plugin failed to run its pre_hook: {}' - 'It will be disabled and its components ' - "won't be loaded.".format(name)) - del config.plugins[name] + run_plugin_pre_hook(config) # Instantiate the database class, ensure that it's of the right type, and # initialize it. Then stash the object on our configuration object. utility_name = ('testing' if testing else 'production') ===================================== src/mailman/docs/NEWS.rst ===================================== @@ -31,6 +31,9 @@ Bugs fixed contained non-ascii. This is fixed. (Closes #965 and #967) * The REST API will now accept JSON encoded data with boolean values for boolean attributes. (Closes #970) +* Fix a bug where loading a plugin which raises an exception in ``pre_hook`` + can cause Mailman to crash trying to disable that plugin. (Closes #724) + .. _news-3.3.5: ===================================== src/mailman/plugins/tests/test_plugins.py ===================================== @@ -21,6 +21,7 @@ import sys import unittest from contextlib import ExitStack +from mailman.core.initialize import run_plugin_pre_hook from mailman.interfaces.plugin import IPlugin from mailman.plugins.initialize import initialize from mailman.plugins.testing.layer import PluginRESTLayer @@ -53,6 +54,16 @@ class TestablePlugin: resource = None +@implementer(IPlugin) +class ExceptionRaisingPlugin: + def pre_hook(self): + raise Exception('Bad plugin') + + def post_hook(self): + pass + resource = None + + class TestInitializePlugins(unittest.TestCase): layer = ConfigLayer @@ -144,3 +155,23 @@ class TestInitializePlugins(unittest.TestCase): initialize() log_mock.info.assert_called_once_with( 'Plugin not enabled, or empty class path: example') + + def test_plugin_disabled_with_exception(self): + with ExitStack() as resources: + system_path = resources.enter_context(TemporaryDirectory()) + fake_plugin_config = { + 'path': system_path, + 'enabled': 'yes', + 'class': 'ExamplePlugin', + } + testable_plugin = ExceptionRaisingPlugin() + fake_mailman_config = SimpleNamespace( + plugin_configs=[('example', fake_plugin_config)], + plugins={'example': testable_plugin}, + ) + + resources.enter_context(patch( + 'mailman.plugins.initialize.call_name', + return_value=testable_plugin)) + run_plugin_pre_hook(fake_mailman_config) + self.assertNotIn('example', fake_mailman_config.plugins) View it on GitLab: https://gitlab.com/mailman/mailman/-/compare/b0dd5d62c3225fbd1db1894d3a04be9facf11e06...4564222d71a241375abfc201224ee03ef4ca0949 -- View it on GitLab: https://gitlab.com/mailman/mailman/-/compare/b0dd5d62c3225fbd1db1894d3a04be9facf11e06...4564222d71a241375abfc201224ee03ef4ca0949 You're receiving this email because of your account on gitlab.com.
_______________________________________________ Mailman-checkins mailing list -- mailman-checkins@python.org To unsubscribe send an email to mailman-checkins-le...@python.org https://mail.python.org/mailman3/lists/mailman-checkins.python.org/ Member address: arch...@jab.org