diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index b95f76eb..68b23696 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -20,7 +20,6 @@ from gunicorn.worker import Worker class Arbiter(object): - LISTENER = None WORKERS = {} PIPE = [] @@ -36,7 +35,7 @@ class Arbiter(object): if name[:3] == "SIG" and name[3] != "_" ) - _pidfile = None + def __init__(self, address, num_workers, modname, **kwargs): @@ -45,15 +44,19 @@ class Arbiter(object): self.modname = modname self.timeout = 30 self.reexec_pid = 0 - self.pid = os.getpid() self.debug = kwargs.get("debug", False) self.log = logging.getLogger(__name__) + self.opts = kwargs + self._pidfile = None + + + def start(self): + self.pid = os.getpid() self.init_signals() self.listen(self.address) - self.pidfile = kwargs.get("pidfile") + self.pidfile = self.opts.get("pidfile") self.log.info("Booted Arbiter: %s" % os.getpid()) - def _del_pidfile(self): self._pidfile = None @@ -180,6 +183,7 @@ class Arbiter(object): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NOPUSH, 1) def run(self): + self.start() self.manage_workers() while True: try: @@ -217,6 +221,7 @@ class Arbiter(object): self.log.info("Master is shutting down.") if self.pidfile: self.unlink_pidfile(self.pidfile) + sys.exit(0) def handle_chld(self, sig, frame): self.wakeup() diff --git a/gunicorn/main.py b/gunicorn/main.py index 4f040bf0..cbaf1f30 100644 --- a/gunicorn/main.py +++ b/gunicorn/main.py @@ -6,6 +6,8 @@ import logging import optparse as op +import os +import sys from gunicorn.arbiter import Arbiter @@ -27,6 +29,8 @@ def options(): help='Number of workers to spawn. [%default]'), op.make_option('-p','--pid', dest='pidfile', help='set the background PID FILE'), + op.make_option('-D', '--daemon', dest='daemon', + help='Run daemonized in the background.'), op.make_option('--log-level', dest='loglevel', default='info', help='Log level below which to silence messages. [%default]'), op.make_option('--log-file', dest='logfile', default='-', @@ -49,11 +53,23 @@ def configure_logging(opts): for h in handlers: h.setFormatter(logging.Formatter("%(levelname)s %(message)s")) logger.addHandler(h) - + return logger + +def daemonize(logger): + if not 'GUNICORN_FD' in os.environ: + pid = os.fork() + if pid != 0: + # Parent + logger.debug("arbiter daemonized; parent exiting") + os._exit(0) + os.close(0) + sys.stdin = sys.__stdin__ = open("/dev/null") + os.setsid() + def main(usage, get_app): parser = op.OptionParser(usage=usage, option_list=options()) opts, args = parser.parse_args() - configure_logging(opts) + logger = configure_logging(opts) app = get_app(parser, opts, args) workers = opts.workers or 1 @@ -74,12 +90,16 @@ def main(usage, get_app): pidfile=opts.pidfile ) + arbiter = Arbiter((host,port), workers, app, **kwargs) + if opts.daemon: + daemonize(logger) arbiter.run() def paste_server(app, global_conf=None, host="127.0.0.1", port=None, *args, **kwargs): + logger = configure_logging(opts) if not port: if ':' in host: host, port = host.split(':', 1) @@ -100,10 +120,16 @@ def paste_server(app, global_conf=None, host="127.0.0.1", port=None, if global_conf: pid = global_conf.get('pid', pid) + daemon = kwargs.get("daemon") + if global_conf: + daemon = global_conf.get('daemon', daemonize) + kwargs = dict( debug=debug, pidfile=pid ) arbiter = Arbiter(bind_addr, workers, app, **kwargs) + if daemon == "true": + daemonize(logger) arbiter.run() \ No newline at end of file diff --git a/gunicorn/worker.py b/gunicorn/worker.py index 873e6af8..8e74c409 100644 --- a/gunicorn/worker.py +++ b/gunicorn/worker.py @@ -60,7 +60,7 @@ class Worker(object): self.alive = False def handle_exit(self, sig, frame): - sys.exit(0) + os._exit(0) def _fchmod(self, mode): if getattr(os, 'fchmod', None):