Commit bc740c5f authored by Jason Madden's avatar Jason Madden

Fix #651 and fix #652 by removing a runtime import.

parent 67ef9936
[pep8] [pep8]
ignore=E702,E265,E402,E731,E266,E261,W503,E129 ignore=E702,E265,E402,E731,E266,E261,W503,E129
max_line_length=160 max_line_length=160
exclude=.eggs,.tox,.git,build,2.6,2.7,2.7pypy,3.3,test_support.py,test_queue.py,patched_tests_setup.py,test_threading_2.py,lock_tests.py,_sslgte279.py,3.4 exclude=.eggs,.tox,.git,build,2.6,2.7,2.7pypy,3.3,3.5,test_support.py,test_queue.py,patched_tests_setup.py,test_threading_2.py,lock_tests.py,_sslgte279.py,3.4
...@@ -36,6 +36,13 @@ ...@@ -36,6 +36,13 @@
``subprocess.run`` but impacts all versions (``timeout`` is an ``subprocess.run`` but impacts all versions (``timeout`` is an
official argument under Python 3 and a gevent extension with official argument under Python 3 and a gevent extension with
slightly different semantics under Python 2). slightly different semantics under Python 2).
- gevent blocking operations performed at the top-level of a module
after the system was monkey-patched under Python 2 could result in
raising a ``LoopExit`` instead of completing the expected blocking
operation. Note that performing gevent blocking operations in the
top-level of a module is typically not recommended, but this
situation can arise when monkey-patching existing scripts. Reported
in :issue:`651` and :issue:`652` by Mike Kaplinskiy.
.. _WSGI specification: https://www.python.org/dev/peps/pep-3333/#the-start-response-callable .. _WSGI specification: https://www.python.org/dev/peps/pep-3333/#the-start-response-callable
......
...@@ -820,19 +820,16 @@ class _MultipleWaiter(Waiter): ...@@ -820,19 +820,16 @@ class _MultipleWaiter(Waiter):
This does not handle exceptions or throw methods. This does not handle exceptions or throw methods.
""" """
_DEQUE = None
__slots__ = ['_values'] __slots__ = ['_values']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
Waiter.__init__(self, *args, **kwargs) Waiter.__init__(self, *args, **kwargs)
self._values = self._deque() # we typically expect a relatively small number of these to be outstanding.
# since we pop from the left, a deque might be slightly
@classmethod # more efficient, but since we're in the hub we avoid imports if
def _deque(cls): # we can help it to better support monkey-patching, and delaying the import
if cls._DEQUE is None: # here can be impractical (see https://github.com/gevent/gevent/issues/652)
from collections import deque self._values = list()
cls._DEQUE = deque
return cls._DEQUE()
def switch(self, value): def switch(self, value):
self._values.append(value) self._values.append(value)
...@@ -843,7 +840,7 @@ class _MultipleWaiter(Waiter): ...@@ -843,7 +840,7 @@ class _MultipleWaiter(Waiter):
Waiter.get(self) Waiter.get(self)
Waiter.clear(self) Waiter.clear(self)
return self._values.popleft() return self._values.pop(0)
def iwait(objects, timeout=None, count=None): def iwait(objects, timeout=None, count=None):
......
# test__import_wait.py calls this
import gevent
def fn2():
return 2
def fn():
return gevent.wait([gevent.spawn(fn2), gevent.spawn(fn2)])
x = gevent.spawn(fn).get()
# https://github.com/gevent/gevent/issues/652
from gevent import monkey
monkey.patch_all()
import _import_wait
assert _import_wait.x
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment