Issue42509
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2020-11-30 06:01 by xxm, last changed 2022-04-11 14:59 by admin. This issue is now closed.
Messages (6) | |||
---|---|---|---|
msg382111 - (view) | Author: Xinmeng Xia (xxm) | Date: 2020-11-30 06:01 | |
The following program 1 can crash in Python 3. We have reproduce it in the Python version 3.5, 3.6, 3.7, 3.8, 3.9, 3.10. This bug seems to be similar to issue 36272, however, the tracking system shows issue 36272 has been fixed and the program 2, which triggers issue 36272, will not cause crash (“core dump”) in Python 3.8, 3.9, 3.10. We have attached the stack trace in the end of this report. Program 1: ======================== import logging def rec(): try: logging.error("foo") except: pass rec() rec() ======================== Program 2: ======================== import logging def rec(): logging.error("foo") rec() rec() ====================== The error message is like following: “ ERROR:root:foo ERROR:root:foo ERROR:root:foo ERROR:root:foo … ERROR:root:foo ERROR:root:foo ERROR:root:foo Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow. Python runtime state: initialized Current thread 0x00007f0fa440b700 (most recent call first): File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 420 in usesTime File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 643 in usesTime File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 675 in format File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 938 in format File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1094 in emit File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 963 in handle File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1673 in callHandlers File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1611 in handle File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1601 in _log File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1483 in error File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 2080 in error File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 8 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec …. File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec ... Aborted (core dumped)” |
|||
msg382112 - (view) | Author: Dennis Sweeney (Dennis Sweeney) * | Date: 2020-11-30 06:51 | |
This might be the expected behavior. See https://bugs.python.org/issue25222 If you already caught a RecursionError and you keep recursing anyway, once you go 50 levels beyond sys.getrecursionlimit(), the interpreter crashes regardless of what is `except`ed. In /Python/ceval.c, there's this: if (tstate->overflowed) { if (tstate->recursion_depth > recursion_limit + 50) { /* Overflowing while handling an overflow. Give up. */ Py_FatalError("Cannot recover from stack overflow."); } return 0; } In your Program 2, when the interpreter raises a `RecursionError`, it is raised normally and everything is fine. In your Program 1, when the interpreter raises a `RecursionError`, it is `except`ed, so the interpreter thinks it's okay to keep going, and when it does, it raises more `RecursionError`s, which it keeps `except`ing, until it finally can't go any farther ( > 50 + sys.getrecursionlimit()), and has no option but to crash. "Cannot recover from stack overflow." seems to make sense to me: when the interpreter tries to recover, the code won't let it. |
|||
msg382114 - (view) | Author: Ronald Oussoren (ronaldoussoren) * | Date: 2020-11-30 08:10 | |
See also #42500 |
|||
msg382117 - (view) | Author: Xinmeng Xia (xxm) | Date: 2020-11-30 08:19 | |
But program like following program 3 will not cause any core dump, RecursionError is also being caught in this Recursion. program 3 def rec(): try: rec() except: pass rec() Beside,I use sys.setrecursionlimit(80), and the program 1 still cause core dump.I print sys.getrecursionlimit(),the value is 1000. 80 is << 50 +1000, it shouldn't cause core dump. |
|||
msg382128 - (view) | Author: Dennis Sweeney (Dennis Sweeney) * | Date: 2020-11-30 09:04 | |
sys.getrecursionlimit() returns whatever was passed to the most recent call of sys.setrecursionlimit(...), with some system default (here 1000). Catching a RecursionError might be fine sometimes, but the issue is that Program 1 catches a RecursionError *and then keeps recursing more* rather than stopping. I think it might have to be the responsibility of the Python user to make sure that if a RecursionError is to be caught, that the program can recover without making things much worse. It's my understanding that the extra buffer of +50 is to make sure that the programmer has room to stop the overflow and do any necessary cleanup [1]. If no attempt is made to clean up, then it seems reasonable to me that Python should crash, unless there's some idea of what could happen that I'm missing. The interpreter could allow arbitrary recursion during the cleanup until the C stack overflows, but that sort of defeats the point of the recursion checker. It could raise some new ExtraSuperRecurionError, but that doesn't fix anything: what if *that* error is caught ;) ? [1] to get back to a recursion depth lower than some lower threshold: https://github.com/python/cpython/blob/master/Include/internal/pycore_ceval.h#L98 |
|||
msg382151 - (view) | Author: Mark Shannon (Mark.Shannon) * | Date: 2020-11-30 14:24 | |
Duplicate of 42500 |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:38 | admin | set | github: 86675 |
2020-11-30 14:24:29 | Mark.Shannon | set | status: open -> closed nosy: + Mark.Shannon messages: + msg382151 resolution: duplicate stage: resolved |
2020-11-30 09:04:41 | Dennis Sweeney | set | messages: + msg382128 |
2020-11-30 08:19:09 | xxm | set | messages: + msg382117 |
2020-11-30 08:10:55 | ronaldoussoren | set | nosy:
+ ronaldoussoren messages: + msg382114 |
2020-11-30 06:51:27 | Dennis Sweeney | set | nosy:
+ Dennis Sweeney messages: + msg382112 |
2020-11-30 06:01:25 | xxm | create |