~abompard/mailman/import21

« back to all changes in this revision

Viewing changes to src/mailman/core/runner.py

  • Committer: Barry Warsaw
  • Date: 2013-06-17 13:36:43 UTC
  • Revision ID: barry@list.org-20130617133643-uj7atdykh2whwabw
 * `bin/runner` command has been simplified and its command line options
   reduced.  Now, only one `-r/--runner` option may be provided and the
   round-robin feature has been removed.
 * Fixed REST server crash on `reopen` command.  Identification and test
   provided by Aurélien Bompard.  (LP: #1184376)

Also:

 * bin/runner now uses standard argparse instead of ScriptOptions.
 * The entire bin/runner machinery has bee reorganized and simplified.  There
 * is no more Loop class.  Signal setting is moved directly into the base
   Runner class and overrided in specific subclasses (e.g. RESTRunner which
   must cleanly shutdown its TCPServer).  The runner exit status is now set
   directly on the Runner instance.
 * Fixed a few minor style issues.
 * In order to cleanly shutdown the RESTRunner's WSGI server, we must start a
   subthread which only watches for an Event and then calls the server's
   shutdown() method.  It has to be this way because the WSGI server itself
   (due to interactions with SQLite), and the signal handlers (due to Python's
   signal handling semantics) must both run in the main thread.  However, the
   shutdown() must be invoked from a subthread in order to prevent deadlock.
 * Refactor the RESTLayer to eliminate duplication of code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 
27
27
 
28
28
import time
 
29
import signal
29
30
import logging
30
31
import traceback
31
32
 
37
38
 
38
39
from mailman.config import config
39
40
from mailman.core.i18n import _
 
41
from mailman.core.logging import reopen
40
42
from mailman.core.switchboard import Switchboard
41
43
from mailman.interfaces.languages import ILanguageManager
42
44
from mailman.interfaces.listmanager import IListManager
46
48
 
47
49
dlog = logging.getLogger('mailman.debug')
48
50
elog = logging.getLogger('mailman.error')
 
51
rlog = logging.getLogger('mailman.runner')
49
52
 
50
53
 
51
54
 
52
55
@implementer(IRunner)
53
56
class Runner:
54
 
    intercept_signals = True
55
57
    is_queue_runner = True
56
58
 
57
59
    def __init__(self, name, slice=None):
85
87
        self.max_restarts = int(section.max_restarts)
86
88
        self.start = as_boolean(section.start)
87
89
        self._stop = False
 
90
        self.status = 0
88
91
 
89
92
    def __repr__(self):
90
93
        return '<{0} at {1:#x}>'.format(self.__class__.__name__, id(self))
91
94
 
 
95
    def signal_handler(self, signum, frame):
 
96
        signame = {
 
97
            signal.SIGTERM: 'SIGTERM',
 
98
            signal.SIGINT: 'SIGINT',
 
99
            signal.SIGUSR1: 'SIGUSR1',
 
100
            }.get(signum, signum)
 
101
        if signum in (signal.SIGTERM, signal.SIGINT, signal.SIGUSR1):
 
102
            self.stop()
 
103
            self.status = signum
 
104
            rlog.info('%s runner caught %s.  Stopping.', self.name, signame)
 
105
        elif signum == signal.SIGHUP:
 
106
            reopen()
 
107
            rlog.info('%s runner caught SIGHUP.  Reopening logs.', self.name)
 
108
 
 
109
    def set_signals(self):
 
110
        """See `IRunner`."""
 
111
        signal.signal(signal.SIGHUP, self.signal_handler)
 
112
        signal.signal(signal.SIGINT, self.signal_handler)
 
113
        signal.signal(signal.SIGTERM, self.signal_handler)
 
114
        signal.signal(signal.SIGUSR1, self.signal_handler)
 
115
 
92
116
    def stop(self):
93
117
        """See `IRunner`."""
94
118
        self._stop = True