prevent infinite recursion with linking to current greenthread

This commit is contained in:
Edward George
2012-12-12 22:19:24 +00:00
parent 2879b70781
commit 05e35c93d1
2 changed files with 28 additions and 4 deletions

View File

@@ -1,3 +1,4 @@
from collections import deque
import sys
from eventlet import event
@@ -156,6 +157,7 @@ class GreenThread(greenlet.greenlet):
def __init__(self, parent):
greenlet.greenlet.__init__(self, self.main, parent)
self._exit_event = event.Event()
self._resolving_links = False
def wait(self):
""" Returns the result of the main function of this GreenThread. If the
@@ -182,7 +184,7 @@ class GreenThread(greenlet.greenlet):
functions by doing things like switching explicitly to another
greenthread.
"""
self._exit_funcs = getattr(self, '_exit_funcs', [])
self._exit_funcs = getattr(self, '_exit_funcs', deque())
self._exit_funcs.append((func, curried_args, curried_kwargs))
if self._exit_event.ready():
self._resolve_links()
@@ -200,9 +202,16 @@ class GreenThread(greenlet.greenlet):
def _resolve_links(self):
# ca and ckw are the curried function arguments
for f, ca, ckw in getattr(self, '_exit_funcs', []):
f(self, *ca, **ckw)
self._exit_funcs = [] # so they don't get called again
if self._resolving_links:
return
self._resolving_links = True
try:
exit_funcs = getattr(self, '_exit_funcs', deque())
while exit_funcs:
f, ca, ckw = exit_funcs.popleft()
f(self, *ca, **ckw)
finally:
self._resolving_links = False
def kill(self, *throw_args):
"""Kills the greenthread using :func:`kill`. After being killed

View File

@@ -86,6 +86,21 @@ class Spawn(LimitedTestCase, Asserts):
gt.link(link_func, 4, b=5)
self.assertEquals(results, [gt, (4,), {'b':5}])
def test_link_relinks(self):
# test that linking in a linked func doesn't cause infinite recursion.
called = []
def link_func(g):
g.link(link_func_pass)
def link_func_pass(g):
called.append(True)
gt = greenthread.spawn(passthru)
gt.link(link_func)
gt.wait()
self.assertEquals(called, [True])
class SpawnAfter(LimitedTestCase, Asserts):
def test_basic(self):
gt = greenthread.spawn_after(0.1, passthru, 20)