tpool: isolate internal socket from default timeout; Thanks to Alex Villacís Lasso
Since commit f37a87b
the internal implementation of tpool uses sockets
instead of pipes for communication. If, for whatever reason, the user code
calls socket.setdefaulttimeout() with some nonzero value, tpool's internal
socket now inherits this timeout. This causes the tpool to receive
a `socket.timeout` exception where none was expected.
https://github.com/eventlet/eventlet/pull/330
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -134,3 +134,4 @@ Thanks To
|
||||
* Alexis Lee
|
||||
* Steven Erenst
|
||||
* Piët Delport
|
||||
* Alex Villacís Lasso
|
||||
|
@@ -276,9 +276,11 @@ def setup():
|
||||
csock.connect(sock.getsockname())
|
||||
csock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
|
||||
_wsock, _addr = sock.accept()
|
||||
_wsock.settimeout(None)
|
||||
_wsock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
|
||||
sock.close()
|
||||
_rsock = greenio.GreenSocket(csock)
|
||||
_rsock.settimeout(None)
|
||||
|
||||
for i in six.moves.range(_nthreads):
|
||||
t = threading.Thread(target=tworker,
|
||||
|
15
tests/isolated/tpool_isolate_socket_default_timeout.py
Normal file
15
tests/isolated/tpool_isolate_socket_default_timeout.py
Normal file
@@ -0,0 +1,15 @@
|
||||
__test__ = False
|
||||
|
||||
if __name__ == '__main__':
|
||||
import eventlet
|
||||
import eventlet.tpool
|
||||
import socket
|
||||
|
||||
def do():
|
||||
eventlet.sleep(0.2)
|
||||
return True
|
||||
|
||||
socket.setdefaulttimeout(0.05)
|
||||
result = eventlet.tpool.execute(do)
|
||||
assert result
|
||||
print('pass')
|
@@ -22,7 +22,7 @@ import time
|
||||
import eventlet
|
||||
from eventlet import tpool, debug, event
|
||||
from eventlet.support import six
|
||||
from tests import LimitedTestCase, skip_with_pyevent, main
|
||||
import tests
|
||||
|
||||
|
||||
one = 1
|
||||
@@ -39,7 +39,7 @@ def raise_exception():
|
||||
raise RuntimeError("hi")
|
||||
|
||||
|
||||
class TestTpool(LimitedTestCase):
|
||||
class TestTpool(tests.LimitedTestCase):
|
||||
def setUp(self):
|
||||
super(TestTpool, self).setUp()
|
||||
|
||||
@@ -47,7 +47,7 @@ class TestTpool(LimitedTestCase):
|
||||
tpool.killall()
|
||||
super(TestTpool, self).tearDown()
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_tuple(self):
|
||||
my_tuple = (1, 2)
|
||||
prox = tpool.Proxy(my_tuple)
|
||||
@@ -55,7 +55,7 @@ class TestTpool(LimitedTestCase):
|
||||
self.assertEqual(prox[1], 2)
|
||||
self.assertEqual(len(my_tuple), 2)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_string(self):
|
||||
my_object = "whatever"
|
||||
prox = tpool.Proxy(my_object)
|
||||
@@ -63,7 +63,7 @@ class TestTpool(LimitedTestCase):
|
||||
self.assertEqual(len(my_object), len(prox))
|
||||
self.assertEqual(my_object.join(['a', 'b']), prox.join(['a', 'b']))
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_uniterable(self):
|
||||
prox = tpool.Proxy([])
|
||||
|
||||
@@ -76,7 +76,7 @@ class TestTpool(LimitedTestCase):
|
||||
self.assertRaises(IndexError, index)
|
||||
self.assertRaises(TypeError, key)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_dict(self):
|
||||
my_object = {'a': 1}
|
||||
prox = tpool.Proxy(my_object)
|
||||
@@ -85,7 +85,7 @@ class TestTpool(LimitedTestCase):
|
||||
self.assertEqual(str(my_object), str(prox))
|
||||
self.assertEqual(repr(my_object), repr(prox))
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_module_class(self):
|
||||
prox = tpool.Proxy(re)
|
||||
self.assertEqual(tpool.Proxy, type(prox))
|
||||
@@ -93,7 +93,7 @@ class TestTpool(LimitedTestCase):
|
||||
self.assertEqual(exp.groups, 3)
|
||||
assert repr(prox.compile)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_eq(self):
|
||||
prox = tpool.Proxy(re)
|
||||
exp1 = prox.compile('.')
|
||||
@@ -102,12 +102,12 @@ class TestTpool(LimitedTestCase):
|
||||
exp3 = prox.compile('/')
|
||||
assert exp1 != exp3
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_ints(self):
|
||||
p = tpool.Proxy(4)
|
||||
assert p == 4
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_hash(self):
|
||||
prox1 = tpool.Proxy('' + 'A')
|
||||
prox2 = tpool.Proxy('A' + '')
|
||||
@@ -118,7 +118,7 @@ class TestTpool(LimitedTestCase):
|
||||
proxList = tpool.Proxy([])
|
||||
self.assertRaises(TypeError, hash, proxList)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_nonzero(self):
|
||||
prox = tpool.Proxy(re)
|
||||
exp1 = prox.compile('.')
|
||||
@@ -126,7 +126,7 @@ class TestTpool(LimitedTestCase):
|
||||
prox2 = tpool.Proxy([1, 2, 3])
|
||||
assert bool(prox2)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_multiple_wraps(self):
|
||||
prox1 = tpool.Proxy(re)
|
||||
prox2 = tpool.Proxy(re)
|
||||
@@ -135,18 +135,18 @@ class TestTpool(LimitedTestCase):
|
||||
del x2
|
||||
prox2.compile('.')
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_getitem(self):
|
||||
prox = tpool.Proxy([0, 1, 2])
|
||||
self.assertEqual(prox[0], 0)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_setitem(self):
|
||||
prox = tpool.Proxy([0, 1, 2])
|
||||
prox[1] = 2
|
||||
self.assertEqual(prox[1], 2)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_iterator(self):
|
||||
self.reset_timeout(2)
|
||||
prox = tpool.Proxy(range(10))
|
||||
@@ -155,7 +155,7 @@ class TestTpool(LimitedTestCase):
|
||||
result.append(i)
|
||||
self.assertEqual(list(range(10)), result)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_wrap_iterator2(self):
|
||||
self.reset_timeout(5) # might take a while due to imprecise sleeping
|
||||
|
||||
@@ -184,7 +184,7 @@ class TestTpool(LimitedTestCase):
|
||||
assert counter[0] > 10, counter[0]
|
||||
gt.kill()
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_raising_exceptions(self):
|
||||
prox = tpool.Proxy(re)
|
||||
|
||||
@@ -196,7 +196,7 @@ class TestTpool(LimitedTestCase):
|
||||
prox = tpool.Proxy(tpool_test)
|
||||
self.assertRaises(RuntimeError, prox.raise_exception)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_variable_and_keyword_arguments_with_function_calls(self):
|
||||
import optparse
|
||||
parser = tpool.Proxy(optparse.OptionParser())
|
||||
@@ -204,7 +204,7 @@ class TestTpool(LimitedTestCase):
|
||||
opts, args = parser.parse_args(["-nfoo"])
|
||||
self.assertEqual(opts.n, 'foo')
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_contention(self):
|
||||
from tests import tpool_test
|
||||
prox = tpool.Proxy(tpool_test)
|
||||
@@ -216,19 +216,19 @@ class TestTpool(LimitedTestCase):
|
||||
results = list(pile)
|
||||
self.assertEqual(len(results), 3)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_timeout(self):
|
||||
import time
|
||||
eventlet.Timeout(0.1, eventlet.TimeoutError())
|
||||
self.assertRaises(eventlet.TimeoutError,
|
||||
tpool.execute, time.sleep, 0.3)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_killall(self):
|
||||
tpool.killall()
|
||||
tpool.setup()
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_killall_remaining_results(self):
|
||||
semaphore = event.Event()
|
||||
|
||||
@@ -244,7 +244,7 @@ class TestTpool(LimitedTestCase):
|
||||
tpool.killall()
|
||||
gt.wait()
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_autowrap(self):
|
||||
x = tpool.Proxy({'a': 1, 'b': 2}, autowrap=(int,))
|
||||
assert isinstance(x.get('a'), tpool.Proxy)
|
||||
@@ -255,7 +255,7 @@ class TestTpool(LimitedTestCase):
|
||||
assert isinstance(x.one, tpool.Proxy)
|
||||
assert not isinstance(x.none, tpool.Proxy)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_autowrap_names(self):
|
||||
x = tpool.Proxy({'a': 1, 'b': 2}, autowrap_names=('get',))
|
||||
assert isinstance(x.get('a'), tpool.Proxy)
|
||||
@@ -265,7 +265,7 @@ class TestTpool(LimitedTestCase):
|
||||
assert isinstance(x.one, tpool.Proxy)
|
||||
assert not isinstance(x.two, tpool.Proxy)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_autowrap_both(self):
|
||||
from tests import tpool_test
|
||||
x = tpool.Proxy(tpool_test, autowrap=(int,), autowrap_names=('one',))
|
||||
@@ -273,7 +273,7 @@ class TestTpool(LimitedTestCase):
|
||||
# violating the abstraction to check that we didn't double-wrap
|
||||
assert not isinstance(x._obj, tpool.Proxy)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_callable(self):
|
||||
def wrapped(arg):
|
||||
return arg
|
||||
@@ -284,7 +284,7 @@ class TestTpool(LimitedTestCase):
|
||||
assert isinstance(x(4), tpool.Proxy)
|
||||
self.assertEqual("4", str(x(4)))
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_callable_iterator(self):
|
||||
def wrapped(arg):
|
||||
yield arg
|
||||
@@ -295,22 +295,22 @@ class TestTpool(LimitedTestCase):
|
||||
for r in x(3):
|
||||
self.assertEqual(3, r)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_eventlet_timeout(self):
|
||||
def raise_timeout():
|
||||
raise eventlet.Timeout()
|
||||
self.assertRaises(eventlet.Timeout, tpool.execute, raise_timeout)
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_tpool_set_num_threads(self):
|
||||
tpool.set_num_threads(5)
|
||||
self.assertEqual(5, tpool._nthreads)
|
||||
|
||||
|
||||
class TpoolLongTests(LimitedTestCase):
|
||||
class TpoolLongTests(tests.LimitedTestCase):
|
||||
TEST_TIMEOUT = 60
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_a_buncha_stuff(self):
|
||||
assert_ = self.assert_
|
||||
|
||||
@@ -339,7 +339,7 @@ class TpoolLongTests(LimitedTestCase):
|
||||
self.assertEqual(len(results), cnt)
|
||||
tpool.killall()
|
||||
|
||||
@skip_with_pyevent
|
||||
@tests.skip_with_pyevent
|
||||
def test_leakage_from_tracebacks(self):
|
||||
tpool.execute(noop) # get it started
|
||||
gc.collect()
|
||||
@@ -362,5 +362,5 @@ class TpoolLongTests(LimitedTestCase):
|
||||
tpool.killall()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
def test_isolate_from_socket_default_timeout():
|
||||
tests.run_isolated('tpool_isolate_socket_default_timeout.py', timeout=1)
|
||||
|
Reference in New Issue
Block a user