diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 13ac8d63aef33c..691642f64f14c7 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -2256,3 +2256,10 @@ Removed * Remove the private ``_Py_InitializeMain()`` function. It was a :term:`provisional API` added to Python 3.8 by :pep:`587`. (Contributed by Victor Stinner in :gh:`129033`.) + +* The undocumented APIs :c:macro:`!Py_C_RECURSION_LIMIT` and + :c:member:`!PyThreadState.c_recursion_remaining`, added in 3.13, are removed + without a deprecation period. + Please use :c:func:`Py_EnterRecursiveCall` to guard against runaway recursion + in C code. + (Removed in :gh:`133079`, see also :gh:`130396`.) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index c562426767c2cb..8a4cd942554657 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -120,8 +120,6 @@ struct _ts { int py_recursion_remaining; int py_recursion_limit; - - int c_recursion_remaining; /* Retained for backwards compatibility. Do not use */ int recursion_headroom; /* Allow 50 more calls to handle any errors. */ /* 'tracing' keeps track of the execution depth when tracing/profiling. @@ -212,8 +210,6 @@ struct _ts { _PyRemoteDebuggerSupport remote_debugger_support; }; -# define Py_C_RECURSION_LIMIT 5000 - /* other API */ /* Similar to PyThreadState_Get(), but don't issue a fatal error diff --git a/Misc/NEWS.d/next/C_API/2025-04-28-13-27-48.gh-issue-133079.DJL2sK.rst b/Misc/NEWS.d/next/C_API/2025-04-28-13-27-48.gh-issue-133079.DJL2sK.rst new file mode 100644 index 00000000000000..436324528611b9 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2025-04-28-13-27-48.gh-issue-133079.DJL2sK.rst @@ -0,0 +1,3 @@ +The undocumented APIs :c:macro:`!Py_C_RECURSION_LIMIT` and +:c:member:`!PyThreadState.c_recursion_remaining`, added in 3.13, are removed +without a deprecation period. diff --git a/Python/pystate.c b/Python/pystate.c index aba558279a657d..934cdd9acd5e6b 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1533,7 +1533,6 @@ init_threadstate(_PyThreadStateImpl *_tstate, tstate->py_recursion_limit = interp->ceval.recursion_limit; tstate->py_recursion_remaining = interp->ceval.recursion_limit; - tstate->c_recursion_remaining = 2; tstate->exc_info = &tstate->exc_state; // PyGILState_Release must not try to delete this thread state. diff --git a/Python/vm-state.md b/Python/vm-state.md index b3246557dbeea3..83b6a577f29e95 100644 --- a/Python/vm-state.md +++ b/Python/vm-state.md @@ -73,7 +73,8 @@ It will be more complex in the JIT. Another important piece of VM state is the **thread state**, held in `tstate`. The current frame pointer, `frame`, is always equal to `tstate->current_frame`. -The thread state also holds the exception state (`tstate->exc_info`) and the recursion counters (`tstate->c_recursion_remaining` and `tstate->py_recursion_remaining`). +The thread state also holds the exception state (`tstate->exc_info`) and +recursion tracking data (`tstate->py_recursion_remaining`, `tstate->c_stack*`). The thread state is also used to access the **interpreter state** (`tstate->interp`), which is important since the "eval breaker" flags are stored there (`tstate->interp->ceval.eval_breaker`, an "atomic" variable), as well as the "PEP 523 function" (`tstate->interp->eval_frame`). The interpreter state also holds the optimizer state (`optimizer` and some counters).