Skip to content

Commit de76a0b

Browse files
authored
[core] Fix python 3.12 asyncio RecursionError leading to objects_valid check (#57253)
Signed-off-by: dayshah <dhyey2019@gmail.com>
1 parent 0c0c245 commit de76a0b

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

python/ray/_raylet.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ cdef extern from "Python.h":
7272
ctypedef struct CPyThreadState "PyThreadState":
7373
int recursion_limit
7474
int recursion_remaining
75+
int c_recursion_remaining
7576

7677
# From Include/ceveal.h#67
7778
int Py_GetRecursionLimit()

python/ray/_raylet.pyx

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -679,29 +679,63 @@ def compute_task_id(ObjectRef object_ref):
679679

680680

681681
cdef 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

707741
cdef CObjectLocationPtrToDict(CObjectLocation* c_object_location):

0 commit comments

Comments
 (0)