From e830a8f54db017a3980588bffa8c9d6e0a2d4eff Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Sat, 23 Jan 2010 18:26:07 +0100 Subject: [PATCH] add debug option and support in paster. It allows us to work with paster in debug mode and some other app that eval results. In debug mode only one worker could be launch and wsgi.multiprocess is set to False. --- gunicorn/arbiter.py | 5 +++-- gunicorn/http/request.py | 17 +++++++++++++++-- gunicorn/main.py | 19 ++++++++++++++++--- gunicorn/worker.py | 6 ++++-- setup.py | 3 +-- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index e23f1bde..19f9fa74 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -32,13 +32,14 @@ class Arbiter(object): if name[:3] == "SIG" and name[3] != "_" ) - def __init__(self, address, num_workers, modname): + def __init__(self, address, num_workers, modname, debug=False): self.address = address self.num_workers = num_workers self.modname = modname self.timeout = 30 self.reexec_pid = 0 self.pid = os.getpid() + self.debug = debug self.log = logging.getLogger(__name__) self.init_signals() self.listen(self.address) @@ -270,7 +271,7 @@ class Arbiter(object): continue worker = Worker(i, self.pid, self.LISTENER, self.modname, - self.timeout) + self.timeout, self.debug) pid = os.fork() if pid != 0: self.WORKERS[pid] = worker diff --git a/gunicorn/http/request.py b/gunicorn/http/request.py index d6ff7b84..9721a5b1 100644 --- a/gunicorn/http/request.py +++ b/gunicorn/http/request.py @@ -43,7 +43,9 @@ class HttpRequest(object): } - def __init__(self, socket, client_address, server_address): + def __init__(self, socket, client_address, server_address, + debug=False): + self.debug = debug self.socket = socket self.client_address = client_address self.server_address = server_address @@ -82,13 +84,24 @@ class HttpRequest(object): else: wsgi_input = TeeInput(self.socket, self.parser, buf[i:]) + + if self.debug: + # according to the doc + # This value should evaluate true if an equivalent application object + # may be simultaneously invoked by another process, and should evaluate + # false otherwise. In debug mode we fall to one worker + # so we comply to pylons and other paster app. + wsgi_multiprocess = False + else: + wsgi_multiprocess = True + environ = { "wsgi.url_scheme": 'http', "wsgi.input": wsgi_input, "wsgi.errors": sys.stderr, "wsgi.version": (1, 0), "wsgi.multithread": False, - "wsgi.multiprocess": True, + "wsgi.multiprocess": wsgi_multiprocess, "wsgi.run_once": False, "SCRIPT_NAME": "", "SERVER_SOFTWARE": self.SERVER_VERSION, diff --git a/gunicorn/main.py b/gunicorn/main.py index 919bb177..5e89147d 100644 --- a/gunicorn/main.py +++ b/gunicorn/main.py @@ -28,7 +28,9 @@ def options(): 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='-', - help='Log to a file. - is stdout. [%default]') + help='Log to a file. - is stdout. [%default]'), + op.make_option('-d', '--debug', dest='debug', action="store_true", + default=False, help='Debug mode. only 1 worker.') ] def configure_logging(opts): @@ -52,7 +54,12 @@ def main(usage, get_app): configure_logging(opts) app = get_app(parser, opts, args) - arbiter = Arbiter((opts.host, opts.port), opts.workers, app) + workers = opts.workers + if opts.debug: + workers = 1 + + arbiter = Arbiter((opts.host, opts.port), workers, app, + opts.debug) arbiter.run() def paste_server(app, global_conf=None, host="127.0.0.1", port=None, @@ -69,5 +76,11 @@ def paste_server(app, global_conf=None, host="127.0.0.1", port=None, else: workers = int(global_conf.get('workers', 1)) - arbiter = Arbiter(bind_addr, workers, app) + debug = global_conf.get('debug') == "true" + if debug: + # we force to one worker in debug mode. + workers = 1 + + arbiter = Arbiter(bind_addr, workers, app, + debug) arbiter.run() \ No newline at end of file diff --git a/gunicorn/worker.py b/gunicorn/worker.py index e6d9874a..9ac365aa 100644 --- a/gunicorn/worker.py +++ b/gunicorn/worker.py @@ -25,9 +25,11 @@ class Worker(object): "HUP QUIT INT TERM TTIN TTOU USR1".split() ) - def __init__(self, workerid, ppid, socket, app, timeout): + def __init__(self, workerid, ppid, socket, app, timeout, + debug=False): self.id = workerid self.ppid = ppid + self.debug = debug self.timeout = timeout / 2.0 fd, tmpname = tempfile.mkstemp() self.tmp = os.fdopen(fd, "r+b") @@ -115,7 +117,7 @@ class Worker(object): def handle(self, client, addr): util.close_on_exec(client) try: - req = http.HttpRequest(client, addr, self.address) + req = http.HttpRequest(client, addr, self.address, self.debug) try: response = self.app(req.read(), req.start_response) except Exception, e: diff --git a/setup.py b/setup.py index abd42136..695a8120 100644 --- a/setup.py +++ b/setup.py @@ -45,5 +45,4 @@ setup( main=gunicorn.main:paste_server """, test_suite = 'nose.collector', -) - +) \ No newline at end of file