Issue36370
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 2019-03-19 19:01 by asmeurer, last changed 2022-04-11 14:59 by admin. This issue is now closed.
Pull Requests | |||
---|---|---|---|
URL | Status | Linked | Edit |
PR 12504 | merged | skrah, 2019-03-22 23:42 | |
PR 12539 | merged | miss-islington, 2019-03-25 20:52 |
Messages (13) | |||
---|---|---|---|
msg338399 - (view) | Author: Aaron Meurer (asmeurer) | Date: 2019-03-19 19:01 | |
I am getting a Fatal Python error: Cannot recover from stack overflow. running the SymPy tests on a branch of mine where the tests fail. I have reproduced this in Python 3.6.7, as well as CPython master (fc96e5474a7bda1c5dec66420e4467fc9f7ca968). Here are the repro steps: 1. Check out my git branch https://github.com/asmeurer/sympy/tree/python-crash 2. Install or point PYTHONPATH to mpmath 3. Run python and type from sympy import test test('sets', subprocess=False) The tests will run (with failures) until they reach a point where Python crashes with Fatal Python error: Cannot recover from stack overflow. Current thread 0x00007fffa8e623c0 (most recent call first): File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/relational.py", line 385 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1594 in _contains File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 286 in contains File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1257 in <genexpr> File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/logic.py", line 139 in fuzzy_and File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1257 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 551 in __sub__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1269 in _handle_finite_sets File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1900 in simplify_intersection File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1200 in __new__ File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 109 in intersect File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 309 in is_subset File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1348 in reduce File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/sets/sets.py", line 1338 in __new__ ... Abort trap: 6 Unfortunately, I'm not able to find a simpler reproducing example for CPython master, as it seems to be heavily dependent on the exact state of the call stack. I also get a crash report from OS X if that's helpful: Process: python.exe [86693] Path: /Users/USER/Documents/*/python.exe Identifier: python.exe Version: 0 Code Type: X86-64 (Native) Parent Process: bash [612] Responsible: python.exe [86693] User ID: 501 Date/Time: 2019-03-19 13:00:28.968 -0600 OS Version: Mac OS X 10.12.6 (16G1917) Report Version: 12 Anonymous UUID: 5AC59B85-E5D2-1EA1-6881-7497830B3180 Sleep/Wake UUID: 44F9CEAE-2035-49EE-A6EF-02AB11D4F067 Time Awake Since Boot: 140000 seconds Time Since Wake: 5200 seconds System Integrity Protection: enabled Crashed Thread: 0 Dispatch queue: com.apple.main-thread Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Application Specific Information: abort() called Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x00007fffa006ed42 __pthread_kill + 10 1 libsystem_pthread.dylib 0x00007fffa015c457 pthread_kill + 90 2 libsystem_c.dylib 0x00007fff9ffd4420 abort + 129 3 python.exe 0x000000010ba4f110 fatal_error + 64 (pylifecycle.c:1983) Thread 0 crashed with X86 Thread State (64-bit): rax: 0x0000000000000000 rbx: 0x0000000000000006 rcx: 0x00007fff542a7c18 rdx: 0x0000000000000000 rdi: 0x0000000000000307 rsi: 0x0000000000000006 rbp: 0x00007fff542a7c40 rsp: 0x00007fff542a7c18 r8: 0x0000000000000040 r9: 0x00007fffa8e46040 r10: 0x0000000008000000 r11: 0x0000000000000206 r12: 0x000000010bb10470 r13: 0x0000000000000000 r14: 0x00007fffa8e623c0 r15: 0x0000000000000000 rip: 0x00007fffa006ed42 rfl: 0x0000000000000206 cr2: 0x00007fffa8e44128 Logical CPU: 0 Error Code: 0x02000148 Trap Number: 133 |
|||
msg338435 - (view) | Author: Karthikeyan Singaravelan (xtreak) * | Date: 2019-03-20 02:42 | |
From the stack trace it looks like some kind of recursion occurs on the tests causing the crash. Sympy is not a part of stdlib. Can you please add a pure Python reproducer or this is something that needs to be fixed by reporting to sympy repo. |
|||
msg338469 - (view) | Author: Rémi Lapeyre (remi.lapeyre) * | Date: 2019-03-20 13:17 | |
FWIW I just tried both f8e46e9e741f253803e9b8be03287e5dd16abd4d and f8e46e9e741f253803e9b8be03287e5dd16abd4d with the reproducer given and none of them segfault. I don't think there is a bug in the Python interpreter, there is some ways to trigger this error when a RecursionError is not handled quickly enough. I suppose you just have a problem in Sympy. I also find suspicious that you reproducer change many lines in Sympy and would look at that first. |
|||
msg338475 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-20 14:32 | |
This occurs when handling a recursion error uses more than 50 extra nested function calls: 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; } You can set the recursion limit with sys.setrecursionlimit(), but it is the extra stack depth that matters here. |
|||
msg338476 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-20 14:38 | |
It can still be an issue in CPython, like in #14537. |
|||
msg338479 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-20 15:09 | |
The tests pass here on Linux with 3.8 (cc60cdd9c4) and a very low sys.setrecursionlimit(150). The fail properly with RecursionError at sys.setrecursionlimit(125). So I guess we'd need a gdb stack trace from OS X in case there's a CPython issue that is OS X specific. |
|||
msg338483 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-20 15:26 | |
Whoops, I tested the wrong branch, getting a proper abort() now. :) |
|||
msg338490 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-20 16:03 | |
The issue is that PyImport_GetModule() can legitimately NULL (not found) but also NULL after an error occurred in PyDict_GetItemWithError(). So one (quick and dirty) approach that fixes this abort() is: diff --git a/Python/import.c b/Python/import.c index bf3a99414f..22eecd7cd6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1735,7 +1735,10 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } mod = PyImport_GetModule(abs_name); - if (mod != NULL && mod != Py_None) { + if (mod == NULL && PyErr_Occurred()) { + goto error; + } + else if (mod != NULL && mod != Py_None) { _Py_IDENTIFIER(__spec__); _Py_IDENTIFIER(_lock_unlock_module); PyObject *spec; cc Brett as the import expert, perhaps he would like another approach. |
|||
msg338496 - (view) | Author: Brett Cannon (brett.cannon) * | Date: 2019-03-20 16:56 | |
Pulling in Eric and Nick as they have played w/ the C API more recently. |
|||
msg338498 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-20 17:10 | |
Actually I just see that this behavior of PyImport_GetModule() is documented: "Return the already imported module with the given name. If the module has not been imported yet then returns NULL but does not set an error. Returns NULL and sets an error if the lookup failed." New in version 3.7. So it should indeed be just a matter of always checking for PyErr_Occurred(). |
|||
msg338822 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-25 20:51 | |
New changeset 027b09c5a13aac9e14a3b43bb385298d549c3833 by Stefan Krah in branch 'master': bpo-36370: Check for PyErr_Occurred() after PyImport_GetModule() (GH-12504) https://github.com/python/cpython/commit/027b09c5a13aac9e14a3b43bb385298d549c3833 |
|||
msg338823 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-25 21:36 | |
New changeset cdd8d4d6dd57f4c9429566706009d4613277d391 by Stefan Krah (Miss Islington (bot)) in branch '3.7': bpo-36370: Check for PyErr_Occurred() after PyImport_GetModule() (GH-12504) https://github.com/python/cpython/commit/cdd8d4d6dd57f4c9429566706009d4613277d391 |
|||
msg338824 - (view) | Author: Stefan Krah (skrah) * | Date: 2019-03-25 21:40 | |
It looks like 3.6 is in security-fix only mode, so it cannot be backported there. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:12 | admin | set | github: 80551 |
2019-03-25 21:40:26 | skrah | set | status: open -> closed versions: + Python 3.7, - Python 3.6 messages: + msg338824 resolution: fixed stage: patch review -> resolved |
2019-03-25 21:36:48 | skrah | set | messages: + msg338823 |
2019-03-25 20:52:35 | miss-islington | set | pull_requests: + pull_request12488 |
2019-03-25 20:51:04 | skrah | set | messages: + msg338822 |
2019-03-23 07:36:33 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka |
2019-03-22 23:42:42 | skrah | set | keywords:
+ patch stage: needs patch -> patch review pull_requests: + pull_request12454 |
2019-03-20 17:10:35 | skrah | set | messages: + msg338498 |
2019-03-20 16:56:18 | brett.cannon | set | nosy:
+ ncoghlan, eric.snow messages: + msg338496 |
2019-03-20 16:09:15 | skrah | set | stage: needs patch |
2019-03-20 16:03:41 | skrah | set | nosy:
+ brett.cannon messages: + msg338490 title: "Fatal Python error: Cannot recover from stack overflow" from SymPy tests -> Check for PyErr_Occurred() after PyImport_GetModule(). |
2019-03-20 15:26:10 | skrah | set | messages: + msg338483 |
2019-03-20 15:09:42 | skrah | set | messages: + msg338479 |
2019-03-20 14:38:42 | skrah | set | messages: + msg338476 |
2019-03-20 14:32:26 | skrah | set | nosy:
+ skrah messages: + msg338475 |
2019-03-20 13:17:58 | remi.lapeyre | set | nosy:
+ remi.lapeyre messages: + msg338469 |
2019-03-20 02:42:21 | xtreak | set | nosy:
+ xtreak messages: + msg338435 |
2019-03-19 19:01:43 | asmeurer | create |