@@ -679,29 +679,63 @@ def compute_task_id(ObjectRef object_ref):
679679
680680
681681cdef increase_recursion_limit():
682- """ Double the recusion limit if current depth is close to the limit"""
682+ """
683+ Ray does some weird things with asio fibers and asyncio to run asyncio actors.
684+ This results in the Python interpreter thinking there's a lot of recursion depth,
685+ so we need to increase the limit when we start getting close.
686+
687+ 0x30C0000 is Python 3.12
688+ On 3.12, when recursion depth increases, c_recursion_remaining will decrease,
689+ and that's what's actually compared to raise a RecursionError. So increasing
690+ it by 1000 when it drops below 1000 will keep us from raising the RecursionError.
691+ https://github.com/python/cpython/blob/bfb9e2f4a4e690099ec2ec53c08b90f4d64fde36/Python/pystate.c#L1353
692+ 0x30B00A4 is Python 3.11
693+ On 3.11, the recursion depth can be calculated with recursion_limit - recursion_remaining.
694+ We can get the current limit with Py_GetRecursionLimit and set it with Py_SetRecursionLimit.
695+ We'll double the limit when there's less than 500 remaining.
696+ On older versions
697+ There's simply a recursion_depth variable and we'll increase the max the same
698+ way we do for 3.11.
699+ """
683700 cdef:
684- CPyThreadState * s = < CPyThreadState * > PyThreadState_Get()
685- int current_limit = Py_GetRecursionLimit()
686- int new_limit = current_limit * 2
687701 cdef extern from * :
688702 """
689703#if PY_VERSION_HEX >= 0x30C0000
690- #define CURRENT_DEPTH(x) ((x)->py_recursion_limit - (x)->py_recursion_remaining)
704+ bool IncreaseRecursionLimitIfNeeded(PyThreadState *x) {
705+ if (x->c_recursion_remaining < 1000) {
706+ x->c_recursion_remaining += 1000;
707+ return true;
708+ }
709+ return false;
710+ }
691711#elif PY_VERSION_HEX >= 0x30B00A4
692- #define CURRENT_DEPTH(x) ((x)->recursion_limit - (x)->recursion_remaining)
712+ bool IncreaseRecursionLimitIfNeeded(PyThreadState *x) {
713+ int current_limit = Py_GetRecursionLimit();
714+ int current_depth = x->recursion_limit - x->recursion_remaining;
715+ if (current_limit - current_depth < 500) {
716+ Py_SetRecursionLimit(current_limit * 2);
717+ return true;
718+ }
719+ return false;
720+ }
693721#else
694- #define CURRENT_DEPTH(x) ((x)->recursion_depth)
722+ bool IncreaseRecursionLimitIfNeeded(PyThreadState *x) {
723+ int current_limit = Py_GetRecursionLimit();
724+ if (current_limit - x->recursion_depth < 500) {
725+ Py_SetRecursionLimit(current_limit * 2);
726+ return true;
727+ }
728+ return false;
729+ }
695730#endif
696731 """
697- int CURRENT_DEPTH(CPyThreadState * x)
698-
699- int current_depth = CURRENT_DEPTH(s)
700- if current_limit - current_depth < 500 :
701- Py_SetRecursionLimit(new_limit)
702- logger.debug(" Increasing Python recursion limit to {} "
703- " current recursion depth is {}." .format(
704- new_limit, current_depth))
732+ c_bool IncreaseRecursionLimitIfNeeded(CPyThreadState * x)
733+
734+ CPyThreadState * s = < CPyThreadState * > PyThreadState_Get()
735+ c_bool increased_recursion_limit = IncreaseRecursionLimitIfNeeded(s)
736+
737+ if increased_recursion_limit:
738+ logger.debug(" Increased Python recursion limit" )
705739
706740
707741cdef CObjectLocationPtrToDict(CObjectLocation* c_object_location):
0 commit comments