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:
Ryan Williams
2009-05-17 19:27:14 -07:00
parent 4fc44ff445
commit 2f62137e89
6 changed files with 31 additions and 23 deletions

View File

@@ -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():

View File

@@ -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)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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):

View File

@@ -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