GeezerVison is showing github.com — Recursions in rust code trigger segmentation faults. · Issue #2796 · RustPython/RustPython
Recursions in rust code trigger segmentation faults. #2796DescriptionCase in point, issues #2783 #2782 #2781 #2780 and #2778.
All these fail due to the same underlying reason, the rust call stack grows until a stack overflow is triggered. RustPython should be able to handle these and raise RecursionError instead, as CPython does. Reacted by Jeong, YunWon, andrew-ld and Snowapril Activitypheki commented on Oct 4, 2021 Sorry I didn't see this issue before opening a duplicate!
I can imagine 3 "simple" solutions:
- Add a
recursion_depth private property to VirtualMachine and increment/decrement it manually on with_frame and with_recursion. This is the way CPython does it and would require a new with_recursion method which would need to be manually called by all potentially recursive rust functions.
- Add an
external_recursion_depth private property and increment it only on with_recursion, using vm.frames.len() + vm.external_recursion_depth to calculate the current recursion depth. This has the same caveat as 1 of needing with_recursion to be manually called.
- Measure the current stack depth by actually looking at the stack, possibly using an external library such as backtrace (see this stackoverflow issue). This has the downside of being platform dependent and less deterministic.
I personally believe 1 is the way to go right now. DimitrisJim commented on Oct 5, 2021 The complexity here appears when you hit the limit since you'd like to handle the RecursionError gracefully when you've possibly run out of stack space. I think there's a crate called stacker that might help with that (but this can be a follow up issue after basic handling of recursion is added).
The first solution is definitely the best approach, an attribute macro that basically does what Py_EnterRecursiveCall/Py_LeaveRecursiveCall would be cool.
Edit: Since you mentioned in the previous issue that you'd like to work on this, I'll go ahead and assign you. pheki commented on Oct 15, 2021 I've found the reference of what CPython does: cpython/include/ceval.h#L49 (notice there's also a link to an email detailing it even more, including problems).
Should this issue be changed to include this or should it be in a new issue?
I also think it's better to open up for anyone to implement this, as I have other priorities and I'm not sure I have the time (although I stand ready for discussion / reviewing). changjoon-park commented on Apr 22, 2026 Filed #7655 with current (2026) reproducers and evidence that this is parser-layer: compile(src, '<s>', 'exec') (which does NOT go through _ast::ast_to_object) and ast.parse() crash at the identical depth threshold (~4000), showing the shared component is rustpython-ruff_python_parser itself.
Also note: #4857 (closed as fixed in 2023) still reproduces on current main — its original ast.parse('+chr(33)' * 1000000) SIGSEGVs.
Prior fixes #7630 (_ast::ast_from_object) and #7632 (json.loads) addressed downstream symptoms; the parser's own recursive descent remains unguarded. youknowone commented on Oct 6, 2026 Deep recursion raises RecursionError instead of aborting the process. The VM checks the Python recursion limit (check_recursive_call) and the C stack (check_c_stack_overflow / with_recursion) before nested native or frame entry.
Closing.
— commented by Grok 4.6
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|