From f2920bfcdaa34c9ec98c47dbb4c63816cd3a580a Mon Sep 17 00:00:00 2001 From: benoitc Date: Mon, 4 Nov 2013 14:26:05 +0100 Subject: [PATCH 1/5] monkey patch in the worker this change move the monkey patching from the aribiter to the worker so we make sure the supervision won't be altered. fix #478 --- gunicorn/workers/geventlet.py | 17 ++++++++++++----- gunicorn/workers/ggevent.py | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/gunicorn/workers/geventlet.py b/gunicorn/workers/geventlet.py index 5c87c8cf..a2448592 100644 --- a/gunicorn/workers/geventlet.py +++ b/gunicorn/workers/geventlet.py @@ -10,6 +10,12 @@ try: import eventlet except ImportError: raise RuntimeError("You need eventlet installed to use this worker.") + +# validate the eventlet version +if eventlet.version_info < (0, 9, 7): + raise RuntimeError("You need eventlet >= 0.9.7") + + from eventlet import hubs from eventlet.greenio import GreenSocket from eventlet.hubs import trampoline @@ -35,11 +41,7 @@ def patch_sendfile(): class EventletWorker(AsyncWorker): - @classmethod - def setup(cls): - import eventlet - if eventlet.version_info < (0, 9, 7): - raise RuntimeError("You need eventlet >= 0.9.7") + def patch(self): eventlet.monkey_patch(os=False) patch_sendfile() @@ -84,3 +86,8 @@ class EventletWorker(AsyncWorker): if te != t: raise [a.kill() for a in acceptors] + + def init_process(self): + # monkey patch here + self.patch() + super(EventletWorker, self).init_process() diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index 0c00f53f..60aba6c2 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -63,8 +63,7 @@ class GeventWorker(AsyncWorker): server_class = None wsgi_handler = None - @classmethod - def setup(cls): + def patch(cls): from gevent import monkey monkey.noisy = False monkey.patch_all() @@ -157,6 +156,9 @@ class GeventWorker(AsyncWorker): if gevent.version_info[0] == 0: def init_process(self): + # monkey patch here + self.patch() + #gevent 0.13 and older doesn't reinitialize dns for us after forking #here's the workaround import gevent.core @@ -164,6 +166,14 @@ class GeventWorker(AsyncWorker): gevent.core.dns_init() super(GeventWorker, self).init_process() + else: + + def init_process(self): + # monkey patch here + self.patch() + # then initialize the process + super(GeventWorker, self).init_process() + class GeventResponse(object): From 9a83d719b23fe28667a9c76bac25ba66651f8ccf Mon Sep 17 00:00:00 2001 From: benoitc Date: Mon, 4 Nov 2013 14:43:40 +0100 Subject: [PATCH 2/5] fix gevent worker --- gunicorn/workers/ggevent.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index 60aba6c2..75d27ea1 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -12,6 +12,8 @@ from datetime import datetime from functools import partial import time +_socket = __import__("socket") + # workaround on osx, disable kqueue if sys.platform == "darwin": os.environ['EVENT_NOKQUEUE'] = "1" @@ -22,7 +24,7 @@ except ImportError: raise RuntimeError("You need gevent installed to use this worker.") from gevent.pool import Pool from gevent.server import StreamServer -from gevent.socket import wait_write +from gevent.socket import wait_write, socket from gevent import pywsgi import gunicorn @@ -63,7 +65,7 @@ class GeventWorker(AsyncWorker): server_class = None wsgi_handler = None - def patch(cls): + def patch(self): from gevent import monkey monkey.noisy = False monkey.patch_all() @@ -71,6 +73,14 @@ class GeventWorker(AsyncWorker): # monkey patch sendfile to make it none blocking patch_sendfile() + # patch sockets + sockets = [] + for s in self.sockets: + sockets.append(socket(s.FAMILY, _socket.SOCK_STREAM, + _sock=s)) + self.sockets = sockets + + def notify(self): super(GeventWorker, self).notify() if self.ppid != os.getppid(): From 308081948fd36d30ed068c14cbf5ba2368805b70 Mon Sep 17 00:00:00 2001 From: benoitc Date: Mon, 4 Nov 2013 14:46:31 +0100 Subject: [PATCH 3/5] fix eventlet worker make sure we patch the listening socket in the worker --- gunicorn/workers/geventlet.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gunicorn/workers/geventlet.py b/gunicorn/workers/geventlet.py index a2448592..84d980e7 100644 --- a/gunicorn/workers/geventlet.py +++ b/gunicorn/workers/geventlet.py @@ -66,6 +66,7 @@ class EventletWorker(AsyncWorker): def run(self): acceptors = [] for sock in self.sockets: + sock = GreenSocket(sock) sock.setblocking(1) hfun = partial(self.handle, sock) acceptor = eventlet.spawn(eventlet.serve, sock, hfun, From e9416b11778ea2ca0b0958c960222394e3878f2d Mon Sep 17 00:00:00 2001 From: Dan Sully Date: Thu, 3 Oct 2013 09:46:55 -0700 Subject: [PATCH 4/5] Include subprocess in the gevent monkey patching to ensure consistent behavior between gevent 1.0b3 and 1.0rc3 --- gunicorn/__init__.py | 2 +- gunicorn/workers/ggevent.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gunicorn/__init__.py b/gunicorn/__init__.py index a0338c0f..dde8b757 100644 --- a/gunicorn/__init__.py +++ b/gunicorn/__init__.py @@ -3,6 +3,6 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -version_info = (18, 0) +version_info = (18, 1) __version__ = ".".join([str(v) for v in version_info]) SERVER_SOFTWARE = "gunicorn/%s" % __version__ diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index 75d27ea1..d3fb7320 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -68,7 +68,7 @@ class GeventWorker(AsyncWorker): def patch(self): from gevent import monkey monkey.noisy = False - monkey.patch_all() + monkey.patch_all(subprocess=True) # monkey patch sendfile to make it none blocking patch_sendfile() From 4ae65eeabf4cc9378c133c7d9b5b06ddc8351a9f Mon Sep 17 00:00:00 2001 From: benoitc Date: Tue, 5 Nov 2013 08:07:57 +0100 Subject: [PATCH 5/5] fix support for current but old stable gevent release --- gunicorn/workers/ggevent.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index d3fb7320..9de521a4 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -68,7 +68,12 @@ class GeventWorker(AsyncWorker): def patch(self): from gevent import monkey monkey.noisy = False - monkey.patch_all(subprocess=True) + + # if the new version is used make sure to patch subprocess + if gevent.version_info[0] == 0: + monkey.patch_all() + else: + monkey.patch_all(subprocess=True) # monkey patch sendfile to make it none blocking patch_sendfile() @@ -181,6 +186,11 @@ class GeventWorker(AsyncWorker): def init_process(self): # monkey patch here self.patch() + + # reinit the hub + from gevent.hub import reinit + hub.reinit() + # then initialize the process super(GeventWorker, self).init_process()