Infinite traceback with greenlets

Issue #2683 new
Antonio Cuni created an issue

Consider the following minimal example:

import traceback
import greenlet

def run_in_b():
    print 2
    A.switch()
    print 4

def run_in_a():
    print 1
    B.switch()
    print 3

A = greenlet.getcurrent()
B = greenlet.greenlet(run_in_b)

run_in_a()
traceback.print_stack(B.gr_frame, 10)

On CPython, it prints simply this:

$ python hangs.py 
1
2
3
  File "hangs.py", line 6, in run_in_b
    A.switch()

On PyPy, there seems to be an endless cycle of frames:

$ pypy hangs.py 
1
2
3
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 190, in _greenlet_start
    res = greenlet.run(*args, **kwds)
  File "hangs.py", line 6, in run_in_b
    A.switch()
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 53, in switch
    return self.__switch('switch', (args, kwds))
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 92, in __switch
    args, kwds = unbound_method(current, *baseargs, to=target)
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 190, in _greenlet_start
    res = greenlet.run(*args, **kwds)
  File "hangs.py", line 6, in run_in_b
    A.switch()
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 53, in switch
    return self.__switch('switch', (args, kwds))
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 92, in __switch
    args, kwds = unbound_method(current, *baseargs, to=target)
  File "/home/antocuni/pypy/default/lib_pypy/greenlet.py", line 190, in _greenlet_start
    res = greenlet.run(*args, **kwds)
  File "hangs.py", line 6, in run_in_b
    A.switch()

This is a minimal example which shows the issue; however, the bug causes issues also with eventlet, in which get_hub().run plays the role of A and an arbitrary spawn()ed function plays the role of B.

Tested with pypy 5.9 and nightly.

Comments (2)

  1. Antonio Cuni reporter

    uhm, looking at pypy/module/_continuation/test_stacklet.py:test_f_back, it seems that this might be the expected behavior of the continulets. In particular, this line suggests so:

        assert f3_foo.f_back is f1_bar    # not running, so a loop
    

    I am not sure whether this behavior is by design or it happens "just because". @arigo , what do you think?

  2. Log in to comment