Issue 28179: Segfault in test_recursionlimit_fatalerror (original) (raw)

This is a follow-up from in issue 27213 (Rework CALL_FUNCTION* opcodes). I believe the test_runpy failure I mentioned there is also the same error, but this one can be reproduced easily.

test_recursionlimit_fatalerror in SysModuleTest (Lib/test/test_sys.py) segfaults on Ubuntu 12.04 (64-bit) with GCC 4.6.3. I compiled Python with the following commands:

$ make distclean
$ ./configure --with-pydebug
$ make -s -j

To reproduce it, run (adapted from the test)

import sys

def f():
    try:
        f()
    except RecursionError:
        f()

sys.setrecursionlimit(10)

f()

I tried with different values like 50, 10, 1000 and the behavior is same.

In case it helps, here is the start of the backtrace:

#2 0x00000000004242fa in Py_FatalError (msg=0x6e0990 "Cannot recover from stack overflow.") at Python/pylifecycle.c:1457 #3 0x00000000005b6bf8 in _Py_CheckRecursiveCall (where=0x6ac0c8 " while calling a Python object") at Python/ceval.c:651 #4 0x000000000045d701 in _PyObject_FastCallDict (func=<built-in method flush of _io.TextIOWrapper object at remote 0x7ffff6607580>, args=0x0, nargs=0, kwargs=0x0) at Objects/abstract.c:2292 #5 0x000000000045e4e9 in callmethod (func=<built-in method flush of _io.TextIOWrapper object at remote 0x7ffff6607580>, format=0x0, va=0x7ffffff36eb0, is_size_t=0) at Objects/abstract.c:2569 #6 0x000000000045e872 in _PyObject_CallMethodId (o=<_io.TextIOWrapper at remote 0x7ffff6607580>, name=0x94c030, format=0x0) at Objects/abstract.c:2626 #7 0x0000000000421ceb in flush_std_files () at Python/pylifecycle.c:515 #8 0x00000000004242f2 in Py_FatalError (msg=0x6e0990 "Cannot recover from stack overflow.") at Python/pylifecycle.c:1436 #9 0x00000000005b6bf8 in _Py_CheckRecursiveCall (where=0x6e09db "") at Python/ceval.c:651 #10 0x00000000005b6f3c in _PyEval_EvalFrameDefault (f=Frame 0xabf4a8, for file a.py, line 3, in f (), throwflag=0) at Python/ceval.c:1003 #11 0x00000000005b6d88 in PyEval_EvalFrameEx (f=Frame 0xabf4a8, for file a.py, line 3, in f (), throwflag=0) at Python/ceval.c:718 Python Exception <class 'gdb.error'> There is no member named dk_entries.: #12 0x00000000005d4b85 in _PyFunction_FastCall (co=0x7ffff65731c0, args=0xabf3e8, nargs=0, globals=) at Python/ceval.c:4845 #13 0x00000000005d4d7a in fast_function (func=<function at remote 0x7ffff6496338>, stack=0xabf3e8, nargs=0, kwnames=0x0) at Python/ceval.c:4880 #14 0x00000000005d4841 in call_function (pp_stack=0x7ffffff39030, oparg=0, kwnames=0x0) at Python/ceval.c:4784 #15 0x00000000005cc464 in _PyEval_EvalFrameDefault (f=Frame 0xabf258, for file a.py, line 5, in f (), throwflag=0) at Python/ceval.c:3250 #16 0x00000000005b6d88 in PyEval_EvalFrameEx (f=Frame 0xabf258, for file a.py, line 5, in f (), throwflag=0) at Python/ceval.c:718 Python Exception <class 'gdb.error'> There is no member named dk_entries.: #17 0x00000000005d4b85 in _PyFunction_FastCall (co=0x7ffff65731c0, args=0xabf198, nargs=0, globals=) at Python/ceval.c:4845 #18 0x00000000005d4d7a in fast_function (func=<function at remote 0x7ffff6496338>, stack=0xabf198, nargs=0, kwnames=0x0) at Python/ceval.c:4880 #19 0x00000000005d4841 in call_function (pp_stack=0x7ffffff3afa0, oparg=0, kwnames=0x0) at Python/ceval.c:4784 #20 0x00000000005cc464 in _PyEval_EvalFrameDefault (f=Frame 0xabf008, for file a.py, line 5, in f (), throwflag=0) at Python/ceval.c:3250 #21 0x00000000005b6d88 in PyEval_EvalFrameEx (f=Frame 0xabf008, for file a.py, line 5, in f (), throwflag=0) at Python/ceval.c:718

What do you mean by crash? I think the purpose of the test is to crash the interpreter:

def test_recursionlimit_fatalerror(self):
    # A fatal error occurs if a second recursion limit is hit when recovering
    # from a first one.

    ...

    self.assertIn(
        b"Fatal Python error: Cannot recover from stack overflow",
        err)

test_sys passes for me in Python 3.5, but not in Python 3.6:

====================================================================== FAIL: test_recursionlimit_fatalerror (test.test_sys.SysModuleTest)

Traceback (most recent call last): File "/home/berker/projects/cpython/default/Lib/test/test_sys.py", line 281, in test_recursionlimit_fatalerror err) AssertionError: b'Fatal Python error: Cannot recover from stack overflow' not found in b''


Running the snippet from in Python 3.6:

$ ./python -V
Python 3.6.0b1+

$ ./python a.py  
Segmentation fault (core dumped)

In Python 3.5:

$ ./python -V
Python 3.5.2+

$ ./python a.py 
Fatal Python error: Cannot recover from stack overflow.

Current thread 0x00007f5965eaf700 (most recent call first):
  File "a.py", line 5 in f
  File "a.py", line 5 in f
  File "a.py", line 5 in f
[...]