diff --git a/gunicorn/config.py b/gunicorn/config.py index 29a42f23..03fa887b 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -630,9 +630,9 @@ class WorkerClass(Setting): A string referring to one of the following bundled classes: * ``sync`` - * ``eventlet`` - Requires eventlet >= 0.9.7 (or install it via + * ``eventlet`` - Requires eventlet >= 0.24 (or install it via ``pip install gunicorn[eventlet]``) - * ``gevent`` - Requires gevent >= 0.13 (or install it via + * ``gevent`` - Requires gevent >= 1.4 (or install it via ``pip install gunicorn[gevent]``) * ``tornado`` - Requires tornado >= 0.2 (or install it via ``pip install gunicorn[tornado]``) diff --git a/gunicorn/workers/geventlet.py b/gunicorn/workers/geventlet.py index b0cf4b83..eda95992 100644 --- a/gunicorn/workers/geventlet.py +++ b/gunicorn/workers/geventlet.py @@ -11,12 +11,11 @@ import sys 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") - + raise RuntimeError("eventlet worker requires eventlet 0.24 or higher") +else: + from pkg_resources import parse_version + if parse_version(eventlet.__version__) < parse_version('0.24'): + raise RuntimeError("eventlet worker requires eventlet 0.24 or higher") from eventlet import hubs, greenthread from eventlet.greenio import GreenSocket @@ -26,6 +25,7 @@ import greenlet from gunicorn.workers.base_async import AsyncWorker + def _eventlet_sendfile(fdout, fdin, offset, nbytes): while True: try: @@ -86,7 +86,7 @@ class EventletWorker(AsyncWorker): def patch(self): hubs.use_hub() - eventlet.monkey_patch(os=False) + eventlet.monkey_patch() patch_sendfile() def is_already_handled(self, respiter): diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index 16dea592..6c614fe2 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -10,20 +10,18 @@ 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" - try: import gevent except ImportError: - raise RuntimeError("You need gevent installed to use this worker.") + raise RuntimeError("gevent worker requires gevent 1.4 or higher") +else: + from pkg_resources import parse_version + if parse_version(gevent.__version__) < parse_version('1.4'): + raise RuntimeError("gevent worker requires gevent 1.4 or higher") + from gevent.pool import Pool from gevent.server import StreamServer -from gevent.socket import wait_write, socket -from gevent import pywsgi +from gevent import hub, monkey, socket, pywsgi import gunicorn from gunicorn.http.wsgi import base_environ @@ -31,13 +29,14 @@ from gunicorn.workers.base_async import AsyncWorker VERSION = "gevent/%s gunicorn/%s" % (gevent.__version__, gunicorn.__version__) + def _gevent_sendfile(fdout, fdin, offset, nbytes): while True: try: return os.sendfile(fdout, fdin, offset, nbytes) except OSError as e: if e.args[0] == errno.EAGAIN: - wait_write(fdout) + socket.wait_write(fdout) else: raise @@ -51,14 +50,7 @@ class GeventWorker(AsyncWorker): wsgi_handler = None def patch(self): - from gevent import monkey - monkey.noisy = False - - # 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_all() # monkey patch sendfile to make it none blocking patch_sendfile() @@ -66,7 +58,7 @@ class GeventWorker(AsyncWorker): # patch sockets sockets = [] for s in self.sockets: - sockets.append(socket(s.FAMILY, _socket.SOCK_STREAM, + sockets.append(socket.socket(s.FAMILY, socket.SOCK_STREAM, fileno=s.sock.fileno())) self.sockets = sockets @@ -165,34 +157,10 @@ class GeventWorker(AsyncWorker): # by deferring to a new greenlet. See #1645 gevent.spawn(super(GeventWorker, self).handle_usr1, sig, frame) - if gevent.version_info[0] == 0: - - def init_process(self): - # monkey patch here - self.patch() - - # reinit the hub - import gevent.core - gevent.core.reinit() - - #gevent 0.13 and older doesn't reinitialize dns for us after forking - #here's the workaround - gevent.core.dns_shutdown(fail_requests=1) - gevent.core.dns_init() - super(GeventWorker, self).init_process() - - else: - - def init_process(self): - # monkey patch here - self.patch() - - # reinit the hub - from gevent import hub - hub.reinit() - - # then initialize the process - super(GeventWorker, self).init_process() + def init_process(self): + self.patch() + hub.reinit() + super(GeventWorker, self).init_process() class GeventResponse(object):