Make Server class octoprint_daemon-aware, make sure terminated() gets invoked on it upon SIGTERM and update respective test

This commit is contained in:
Kyle Evans 2016-05-06 16:18:57 -05:00
parent 1b1148d0c6
commit 75f8facb05
4 changed files with 13 additions and 21 deletions

View file

@ -11,7 +11,7 @@ import sys
from octoprint.cli import pass_octoprint_ctx, bulk_options, standard_options from octoprint.cli import pass_octoprint_ctx, bulk_options, standard_options
def run_server(basedir, configfile, host, port, debug, allow_root, logging_config, verbosity): def run_server(basedir, configfile, host, port, debug, allow_root, logging_config, verbosity, octoprint_daemon = None):
"""Initializes the environment and starts up the server.""" """Initializes the environment and starts up the server."""
from octoprint import init_platform, __display_version__ from octoprint import init_platform, __display_version__
@ -38,7 +38,7 @@ def run_server(basedir, configfile, host, port, debug, allow_root, logging_confi
after_logging=log_startup) after_logging=log_startup)
from octoprint.server import Server from octoprint.server import Server
octoprint_server = Server(settings=settings, plugin_manager=plugin_manager, host=host, port=port, debug=debug, allow_root=allow_root) octoprint_server = Server(settings=settings, plugin_manager=plugin_manager, host=host, port=port, debug=debug, allow_root=allow_root, octoprint_daemon=octoprint_daemon)
octoprint_server.run() octoprint_server.run()
#~~ server options #~~ server options
@ -114,7 +114,7 @@ def daemon_command(octoprint_ctx, pid, host, port, logging, allow_root, debug, c
self._verbosity = verbosity self._verbosity = verbosity
def run(self): def run(self):
run_server(self._basedir, self._configfile, self._host, self._port, self._debug, self._allow_root, self._logging_config, self._verbosity) run_server(self._basedir, self._configfile, self._host, self._port, self._debug, self._allow_root, self._logging_config, self._verbosity, self)
octoprint_daemon = OctoPrintDaemon(pid, octoprint_ctx.basedir, octoprint_ctx.configfile, octoprint_daemon = OctoPrintDaemon(pid, octoprint_ctx.basedir, octoprint_ctx.configfile,
host, port, debug, allow_root, logging, octoprint_ctx.verbosity) host, port, debug, allow_root, logging, octoprint_ctx.verbosity)

View file

@ -31,9 +31,6 @@ class Daemon:
pid = str(os.getpid()) pid = str(os.getpid())
self.set_pid(pid) self.set_pid(pid)
# register listener for SIGTERM
signal.signal(signal.SIGTERM, self._on_sigterm)
def _double_fork(self): def _double_fork(self):
try: try:
pid = os.fork() pid = os.fork()
@ -71,10 +68,8 @@ class Daemon:
os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno()) os.dup2(se.fileno(), sys.stderr.fileno())
def _on_sigterm(self, _signo, _stack_frame): def terminated(self):
"""Signal handler for SIGTERM, deletes the pidfile."""
self.remove_pidfile() self.remove_pidfile()
sys.exit(0)
def start(self): def start(self):
"""Start the daemon.""" """Start the daemon."""

View file

@ -113,13 +113,14 @@ def load_user(id):
class Server(object): class Server(object):
def __init__(self, settings=None, plugin_manager=None, host="0.0.0.0", port=5000, debug=False, allow_root=False): def __init__(self, settings=None, plugin_manager=None, host="0.0.0.0", port=5000, debug=False, allow_root=False, octoprint_daemon=None):
self._settings = settings self._settings = settings
self._plugin_manager = plugin_manager self._plugin_manager = plugin_manager
self._host = host self._host = host
self._port = port self._port = port
self._debug = debug self._debug = debug
self._allow_root = allow_root self._allow_root = allow_root
self._octoprint_daemon = octoprint_daemon
self._server = None self._server = None
self._logger = None self._logger = None
@ -515,6 +516,11 @@ class Server(object):
octoprint.plugin.call_plugin(octoprint.plugin.ShutdownPlugin, octoprint.plugin.call_plugin(octoprint.plugin.ShutdownPlugin,
"on_shutdown", "on_shutdown",
sorting_context="ShutdownPlugin.on_shutdown") sorting_context="ShutdownPlugin.on_shutdown")
if self._octoprint_daemon is not None:
self._logger.info("Cleaning up daemon pidfile")
self._octoprint_daemon.terminated()
self._logger.info("Goodbye!") self._logger.info("Goodbye!")
atexit.register(on_shutdown) atexit.register(on_shutdown)

View file

@ -155,25 +155,16 @@ class DaemonTest(unittest.TestCase):
self.daemon._double_fork.assert_called_once_with() self.daemon._double_fork.assert_called_once_with()
self.daemon._redirect_io.assert_called_once_with() self.daemon._redirect_io.assert_called_once_with()
self.daemon.set_pid.assert_called_once_with(str(pid)) self.daemon.set_pid.assert_called_once_with(str(pid))
mock_signal.assert_called_once_with(signal.SIGTERM, self.daemon._on_sigterm)
@mock.patch("sys.exit") def test_terminated(self):
def test_on_sigterm(self, mock_exit):
# setup # setup
self.daemon.remove_pidfile = mock.MagicMock() self.daemon.remove_pidfile = mock.MagicMock()
mock_exit.side_effect = ExpectedExit
# test # test
try: self.daemon.terminated()
self.daemon._on_sigterm("foo", "bar")
self.fail("Expected an exit")
except ExpectedExit:
pass
# assert # assert
self.daemon.remove_pidfile.assert_called_once_with() self.daemon.remove_pidfile.assert_called_once_with()
mock_exit.assert_called_once_with(0)
def test_start(self): def test_start(self):
# setup # setup