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/geventlet.py b/gunicorn/workers/geventlet.py index 5c87c8cf..84d980e7 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() @@ -64,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, @@ -84,3 +87,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..9de521a4 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,15 +65,27 @@ class GeventWorker(AsyncWorker): server_class = None wsgi_handler = None - @classmethod - def setup(cls): + def patch(self): from gevent import monkey monkey.noisy = False - monkey.patch_all() + + # 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() + # 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(): @@ -157,6 +171,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 +181,19 @@ class GeventWorker(AsyncWorker): gevent.core.dns_init() super(GeventWorker, self).init_process() + else: + + 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() + class GeventResponse(object):