Removed exc_greenlet from the hubs and the waiters_by_greenlet dict that was needed to support that functionality because the try/finally around hub.switch in trampoline does the right thing already. Added a unit test to verify that this still works.
This commit is contained in:
@@ -431,7 +431,7 @@ def exc_after(seconds, *throw_args):
|
||||
timer.cancel()
|
||||
"""
|
||||
hub = get_hub()
|
||||
return call_after(seconds, hub.exc_greenlet, getcurrent(), *throw_args)
|
||||
return call_after(seconds, getcurrent().throw, *throw_args)
|
||||
|
||||
|
||||
def get_default_hub():
|
||||
|
@@ -41,7 +41,6 @@ class BaseHub(object):
|
||||
self.readers = {}
|
||||
self.writers = {}
|
||||
self.excs = {}
|
||||
self.waiters_by_greenlet = {}
|
||||
|
||||
self.clock = clock
|
||||
self.greenlet = greenlet.greenlet(self.run)
|
||||
@@ -87,20 +86,12 @@ class BaseHub(object):
|
||||
self.excs[fileno] = exc
|
||||
else:
|
||||
self.excs.pop(fileno, None)
|
||||
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
|
||||
return fileno
|
||||
|
||||
def remove_descriptor(self, fileno):
|
||||
self.readers.pop(fileno, None)
|
||||
self.writers.pop(fileno, None)
|
||||
self.excs.pop(fileno, None)
|
||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), None)
|
||||
|
||||
def exc_greenlet(self, gr, *throw_args):
|
||||
fileno = self.waiters_by_greenlet.pop(gr, None)
|
||||
if fileno is not None:
|
||||
self.remove_descriptor(fileno)
|
||||
gr.throw(*throw_args)
|
||||
|
||||
def exc_descriptor(self, fileno):
|
||||
exc = self.excs.get(fileno)
|
||||
|
@@ -66,7 +66,6 @@ class Hub(hub.BaseHub):
|
||||
if exc:
|
||||
self.excs[fileno] = exc
|
||||
|
||||
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
|
||||
return fileno
|
||||
|
||||
def remove_descriptor(self, fileno):
|
||||
@@ -75,7 +74,6 @@ class Hub(hub.BaseHub):
|
||||
if tpl is not None:
|
||||
tpl[0].stop()
|
||||
self.excs.pop(fileno, None)
|
||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), None)
|
||||
|
||||
def abort(self):
|
||||
super(Hub, self).abort()
|
||||
|
@@ -72,7 +72,6 @@ class Hub(hub.BaseHub):
|
||||
if exc:
|
||||
self.excs[fileno] = exc
|
||||
|
||||
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
|
||||
return fileno
|
||||
|
||||
def remove_descriptor(self, fileno):
|
||||
@@ -81,7 +80,6 @@ class Hub(hub.BaseHub):
|
||||
if tpl is not None:
|
||||
tpl[0].delete()
|
||||
self.excs.pop(fileno, None)
|
||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), None)
|
||||
|
||||
def abort(self):
|
||||
super(Hub, self).abort()
|
||||
|
@@ -106,7 +106,6 @@ class BaseTwistedHub(object):
|
||||
|
||||
def __init__(self, mainloop_greenlet):
|
||||
self.greenlet = mainloop_greenlet
|
||||
self.waiters_by_greenlet = {}
|
||||
|
||||
def switch(self):
|
||||
assert api.getcurrent() is not self.greenlet, "Cannot switch from MAINLOOP to MAINLOOP"
|
||||
@@ -128,20 +127,12 @@ class BaseTwistedHub(object):
|
||||
if write:
|
||||
reactor.addWriter(descriptor)
|
||||
# XXX exc will not work if no read nor write
|
||||
self.waiters_by_greenlet[api.getcurrent()] = descriptor
|
||||
return descriptor
|
||||
|
||||
def remove_descriptor(self, descriptor):
|
||||
from twisted.internet import reactor
|
||||
reactor.removeReader(descriptor)
|
||||
reactor.removeWriter(descriptor)
|
||||
self.waiters_by_greenlet.pop(api.getcurrent(), None)
|
||||
|
||||
def exc_greenlet(self, gr, *throw_args):
|
||||
fileno = self.waiters_by_greenlet.pop(gr, None)
|
||||
if fileno is not None:
|
||||
self.remove_descriptor(fileno)
|
||||
gr.throw(*throw_args)
|
||||
|
||||
# required by GreenSocket
|
||||
def exc_descriptor(self, _fileno):
|
||||
|
@@ -186,6 +186,36 @@ class TestApi(tests.TestCase):
|
||||
self.assertRaises(
|
||||
ImportError, api.named, 'this_name_should_hopefully_not_exist.Foo')
|
||||
|
||||
def test_timeout_and_final_write(self):
|
||||
# This test verifies that a write on a socket that we've
|
||||
# stopped listening for doesn't result in an incorrect switch
|
||||
from eventlet import greenio
|
||||
rpipe, wpipe = os.pipe()
|
||||
rfile = os.fdopen(rpipe,"r",0)
|
||||
wrap_rfile = greenio.GreenPipe(rfile)
|
||||
wfile = os.fdopen(wpipe,"w",0)
|
||||
wrap_wfile = greenio.GreenPipe(wfile)
|
||||
|
||||
def sender(evt):
|
||||
api.sleep(0.02)
|
||||
wrap_wfile.write('hi')
|
||||
evt.send('sent via event')
|
||||
|
||||
from eventlet import coros
|
||||
evt = coros.event()
|
||||
api.spawn(sender, evt)
|
||||
try:
|
||||
# try and get some data off of this pipe
|
||||
# but bail before any is sent
|
||||
api.exc_after(0.01, api.TimeoutError)
|
||||
_c = wrap_rfile.read(1)
|
||||
self.fail()
|
||||
except api.TimeoutError:
|
||||
pass
|
||||
|
||||
result = evt.wait()
|
||||
self.assertEquals(result, 'sent via event')
|
||||
|
||||
|
||||
class Foo(object):
|
||||
pass
|
||||
|
Reference in New Issue
Block a user