Merge pull request #1437 from jodal/fix/1435-stop-on-sigterm

Stop GLib mainloop on SIGTERM
This commit is contained in:
Stein Magnus Jodal 2016-02-10 21:59:33 +01:00
commit be568b769f
3 changed files with 22 additions and 12 deletions

View File

@ -27,7 +27,7 @@ def main():
log.bootstrap_delayed_logging()
logger.info('Starting Mopidy %s', versioning.get_version())
signal.signal(signal.SIGTERM, process.exit_handler)
signal.signal(signal.SIGTERM, process.sigterm_handler)
# Windows does not have signal.SIGUSR1
if hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, pykka.debug.log_thread_tracebacks)

View File

@ -5,6 +5,7 @@ import collections
import contextlib
import logging
import os
import signal
import sys
import pykka
@ -13,7 +14,7 @@ from mopidy import config as config_lib, exceptions
from mopidy.audio import Audio
from mopidy.core import Core
from mopidy.internal import deps, process, timer, versioning
from mopidy.internal.gi import GLib, GObject
from mopidy.internal.gi import GLib
logger = logging.getLogger(__name__)
@ -283,7 +284,13 @@ class RootCommand(Command):
help='`section/key=value` values to override config options')
def run(self, args, config):
loop = GObject.MainLoop()
def on_sigterm(loop):
logger.info('GLib mainloop got SIGTERM. Exiting...')
loop.quit()
loop = GLib.MainLoop()
GLib.unix_signal_add(
GLib.PRIORITY_DEFAULT, signal.SIGTERM, on_sigterm, loop)
mixer_class = self.get_mixer_class(config, args.registry['mixer'])
backend_classes = args.registry['backend']
@ -300,6 +307,7 @@ class RootCommand(Command):
backends = self.start_backends(config, backend_classes, audio)
core = self.start_core(config, mixer, backends, audio)
self.start_frontends(config, frontend_classes, core)
logger.info('Starting GLib mainloop')
loop.run()
except (exceptions.BackendError,
exceptions.FrontendError,

View File

@ -1,7 +1,6 @@
from __future__ import absolute_import, unicode_literals
import logging
import signal
import threading
import pykka
@ -12,20 +11,23 @@ from mopidy.compat import thread
logger = logging.getLogger(__name__)
SIGNALS = dict(
(k, v) for v, k in signal.__dict__.items()
if v.startswith('SIG') and not v.startswith('SIG_'))
def exit_process():
logger.debug('Interrupting main...')
thread.interrupt_main()
logger.debug('Interrupted main')
def exit_handler(signum, frame):
"""A :mod:`signal` handler which will exit the program on signal."""
logger.info('Got %s signal', SIGNALS[signum])
def sigterm_handler(signum, frame):
"""A :mod:`signal` handler which will exit the program on signal.
This function is not called when the process' main thread is running a GLib
mainloop. In that case, the GLib mainloop must listen for SIGTERM signals
and quit itself.
For Mopidy subcommands that does not run the GLib mainloop, this handler
ensures a proper shutdown of the process on SIGTERM.
"""
logger.info('Got SIGTERM signal. Exiting...')
exit_process()