monkeypatch wsgi.sendfile for gevent

make sendfile usage non blocking with gevent
This commit is contained in:
benoitc 2013-08-27 18:18:35 +02:00
parent 4e3702c3ca
commit 25094605cf
2 changed files with 23 additions and 1 deletions

View File

@ -18,7 +18,7 @@ try:
from os import sendfile from os import sendfile
except ImportError: except ImportError:
try: try:
from _sendfile import sendfile from ._sendfile import sendfile
except ImportError: except ImportError:
sendfile = None sendfile = None

View File

@ -5,6 +5,7 @@
from __future__ import with_statement from __future__ import with_statement
import errno
import os import os
import sys import sys
from datetime import datetime from datetime import datetime
@ -21,13 +22,31 @@ except ImportError:
raise RuntimeError("You need gevent installed to use this worker.") raise RuntimeError("You need gevent installed to use this worker.")
from gevent.pool import Pool from gevent.pool import Pool
from gevent.server import StreamServer from gevent.server import StreamServer
from gevent.socket import wait_write
from gevent import pywsgi from gevent import pywsgi
import gunicorn import gunicorn
from gunicorn.workers.async import AsyncWorker from gunicorn.workers.async import AsyncWorker
from gunicorn.http.wsgi import sendfile as o_sendfile
VERSION = "gevent/%s gunicorn/%s" % (gevent.__version__, gunicorn.__version__) VERSION = "gevent/%s gunicorn/%s" % (gevent.__version__, gunicorn.__version__)
def _gevent_sendfile(fdout, fdin, offset, nbytes):
while True:
try:
return o_sendfile(fdout, fdin, offset, nbytes)
except OSError as e:
if e.args[0] == errno.EAGAIN:
wait_write(fdout)
else:
raise
def patch_sendfile():
from gunicorn.http import wsgi
if o_sendfile is not None:
setattr(wsgi, "sendfile", _gevent_sendfile)
BASE_WSGI_ENV = { BASE_WSGI_ENV = {
'GATEWAY_INTERFACE': 'CGI/1.1', 'GATEWAY_INTERFACE': 'CGI/1.1',
'SERVER_SOFTWARE': VERSION, 'SERVER_SOFTWARE': VERSION,
@ -50,6 +69,9 @@ class GeventWorker(AsyncWorker):
monkey.noisy = False monkey.noisy = False
monkey.patch_all() monkey.patch_all()
# monkey patch sendfile to make it none blocking
patch_sendfile()
def notify(self): def notify(self):
super(GeventWorker, self).notify() super(GeventWorker, self).notify()
if self.ppid != os.getppid(): if self.ppid != os.getppid():