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()
|
timer.cancel()
|
||||||
"""
|
"""
|
||||||
hub = get_hub()
|
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():
|
def get_default_hub():
|
||||||
|
@@ -41,7 +41,6 @@ class BaseHub(object):
|
|||||||
self.readers = {}
|
self.readers = {}
|
||||||
self.writers = {}
|
self.writers = {}
|
||||||
self.excs = {}
|
self.excs = {}
|
||||||
self.waiters_by_greenlet = {}
|
|
||||||
|
|
||||||
self.clock = clock
|
self.clock = clock
|
||||||
self.greenlet = greenlet.greenlet(self.run)
|
self.greenlet = greenlet.greenlet(self.run)
|
||||||
@@ -87,20 +86,12 @@ class BaseHub(object):
|
|||||||
self.excs[fileno] = exc
|
self.excs[fileno] = exc
|
||||||
else:
|
else:
|
||||||
self.excs.pop(fileno, None)
|
self.excs.pop(fileno, None)
|
||||||
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
|
|
||||||
return fileno
|
return fileno
|
||||||
|
|
||||||
def remove_descriptor(self, fileno):
|
def remove_descriptor(self, fileno):
|
||||||
self.readers.pop(fileno, None)
|
self.readers.pop(fileno, None)
|
||||||
self.writers.pop(fileno, None)
|
self.writers.pop(fileno, None)
|
||||||
self.excs.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):
|
def exc_descriptor(self, fileno):
|
||||||
exc = self.excs.get(fileno)
|
exc = self.excs.get(fileno)
|
||||||
|
@@ -66,7 +66,6 @@ class Hub(hub.BaseHub):
|
|||||||
if exc:
|
if exc:
|
||||||
self.excs[fileno] = exc
|
self.excs[fileno] = exc
|
||||||
|
|
||||||
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
|
|
||||||
return fileno
|
return fileno
|
||||||
|
|
||||||
def remove_descriptor(self, fileno):
|
def remove_descriptor(self, fileno):
|
||||||
@@ -75,7 +74,6 @@ class Hub(hub.BaseHub):
|
|||||||
if tpl is not None:
|
if tpl is not None:
|
||||||
tpl[0].stop()
|
tpl[0].stop()
|
||||||
self.excs.pop(fileno, None)
|
self.excs.pop(fileno, None)
|
||||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), None)
|
|
||||||
|
|
||||||
def abort(self):
|
def abort(self):
|
||||||
super(Hub, self).abort()
|
super(Hub, self).abort()
|
||||||
|
@@ -72,7 +72,6 @@ class Hub(hub.BaseHub):
|
|||||||
if exc:
|
if exc:
|
||||||
self.excs[fileno] = exc
|
self.excs[fileno] = exc
|
||||||
|
|
||||||
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
|
|
||||||
return fileno
|
return fileno
|
||||||
|
|
||||||
def remove_descriptor(self, fileno):
|
def remove_descriptor(self, fileno):
|
||||||
@@ -81,7 +80,6 @@ class Hub(hub.BaseHub):
|
|||||||
if tpl is not None:
|
if tpl is not None:
|
||||||
tpl[0].delete()
|
tpl[0].delete()
|
||||||
self.excs.pop(fileno, None)
|
self.excs.pop(fileno, None)
|
||||||
self.waiters_by_greenlet.pop(greenlet.getcurrent(), None)
|
|
||||||
|
|
||||||
def abort(self):
|
def abort(self):
|
||||||
super(Hub, self).abort()
|
super(Hub, self).abort()
|
||||||
|
@@ -106,7 +106,6 @@ class BaseTwistedHub(object):
|
|||||||
|
|
||||||
def __init__(self, mainloop_greenlet):
|
def __init__(self, mainloop_greenlet):
|
||||||
self.greenlet = mainloop_greenlet
|
self.greenlet = mainloop_greenlet
|
||||||
self.waiters_by_greenlet = {}
|
|
||||||
|
|
||||||
def switch(self):
|
def switch(self):
|
||||||
assert api.getcurrent() is not self.greenlet, "Cannot switch from MAINLOOP to MAINLOOP"
|
assert api.getcurrent() is not self.greenlet, "Cannot switch from MAINLOOP to MAINLOOP"
|
||||||
@@ -128,20 +127,12 @@ class BaseTwistedHub(object):
|
|||||||
if write:
|
if write:
|
||||||
reactor.addWriter(descriptor)
|
reactor.addWriter(descriptor)
|
||||||
# XXX exc will not work if no read nor write
|
# XXX exc will not work if no read nor write
|
||||||
self.waiters_by_greenlet[api.getcurrent()] = descriptor
|
|
||||||
return descriptor
|
return descriptor
|
||||||
|
|
||||||
def remove_descriptor(self, descriptor):
|
def remove_descriptor(self, descriptor):
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
reactor.removeReader(descriptor)
|
reactor.removeReader(descriptor)
|
||||||
reactor.removeWriter(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
|
# required by GreenSocket
|
||||||
def exc_descriptor(self, _fileno):
|
def exc_descriptor(self, _fileno):
|
||||||
|
@@ -186,6 +186,36 @@ class TestApi(tests.TestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
ImportError, api.named, 'this_name_should_hopefully_not_exist.Foo')
|
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):
|
class Foo(object):
|
||||||
pass
|
pass
|
||||||
|
Reference in New Issue
Block a user