Fix HTTPServer.serve_forever blocking whole process

Original report: https://github.com/eventlet/eventlet/issues/249

Explanation is in the comments in the code.

Originally reverted[1] because a commit preceding it[2] broke the build
but it wasn't clear what commit was responsible.

[1] 02b693a45d
[2] 4656eadfa5
This commit is contained in:
Jakub Stasiak
2015-11-12 02:05:25 +01:00
parent 3ae710e70e
commit 0d509ef7d2
4 changed files with 59 additions and 1 deletions

View File

@@ -3,9 +3,29 @@ import sys
from eventlet import patcher
from eventlet.green import select
__patched__ = [
'SelectSelector',
'PollSelector',
'EpollSelector',
'DevpollSelector',
'KqueueSelector',
]
patcher.inject('selectors', globals(), ('select', select))
del patcher
if sys.platform != 'win32':
SelectSelector._select = staticmethod(select.select)
# We only have green select so the options are:
# * leave it be and have selectors that block
# * try to pretend the "bad" selectors don't exist
# * replace all with SelectSelector for the price of possibly different
# performance characteristic and missing fileno() method (if someone
# uses it it'll result in a crash, we may want to implement it in the future)
PollSelector = SelectSelector
EpollSelector = SelectSelector
DevpollSelector = SelectSelector
KqueueSelector = SelectSelector

View File

@@ -331,7 +331,13 @@ def _green_os_modules():
def _green_select_modules():
from eventlet.green import select
return [('select', select)]
modules = [('select', select)]
if sys.version_info >= (3, 4):
from eventlet.green import selectors
modules.append(('selectors', selectors))
return modules
def _green_socket_modules():

View File

@@ -0,0 +1,28 @@
if __name__ == '__main__':
import eventlet
eventlet.monkey_patch()
from eventlet.support.six.moves.BaseHTTPServer import (
HTTPServer,
BaseHTTPRequestHandler,
)
import threading
server = HTTPServer(('localhost', 0), BaseHTTPRequestHandler)
thread = threading.Thread(target=server.serve_forever)
# Before fixing it the code would never go pass this line because:
# * socketserver.BaseServer that's used behind the scenes here uses
# selectors.PollSelector if it's available and we don't have green poll
# implementation so this just couldn't work
# * making socketserver use selectors.SelectSelector wasn't enough as
# until now we just failed to monkey patch selectors module
#
# Due to the issues above this thread.start() call effectively behaved
# like calling server.serve_forever() directly in the current thread
#
# Original report: https://github.com/eventlet/eventlet/issues/249
thread.start()
server.shutdown()
print('pass')

View File

@@ -506,3 +506,7 @@ def test_threading_condition():
def test_threading_join():
tests.run_isolated('patcher_threading_join.py')
def test_socketserver_selectors():
tests.run_isolated('patcher_socketserver_selectors.py')