prevent infinite recursion with linking to current greenthread
This commit is contained in:
@@ -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', []):
|
||||
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)
|
||||
self._exit_funcs = [] # so they don't get called again
|
||||
finally:
|
||||
self._resolving_links = False
|
||||
|
||||
def kill(self, *throw_args):
|
||||
"""Kills the greenthread using :func:`kill`. After being killed
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user