diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index ae6ef9aabac146..383c98dc167cda 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -15,9 +15,10 @@ struct _frame; #include "pycore_pystate.h" /* PyInterpreterState.eval_frame */ -PyAPI_FUNC(void) _Py_FinishPendingCalls(PyThreadState *tstate); -PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *); -PyAPI_FUNC(void) _PyEval_FiniThreads( +extern void _Py_FinishPendingCalls(PyThreadState *tstate); +extern void _PyEval_InitializeRuntime(struct _ceval_runtime_state *); +extern void _PyEval_InitializeInterp(struct _ceval_state *); +extern void _PyEval_FiniThreads( struct _ceval_runtime_state *ceval); PyAPI_FUNC(void) _PyEval_SignalReceived( struct _ceval_runtime_state *ceval); diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 0a835463625580..36ef50bd002715 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -34,7 +34,6 @@ struct _pending_calls { }; struct _ceval_runtime_state { - int recursion_limit; /* Records whether tracing is on for any thread. Counts the number of threads for which tstate->c_tracefunc is non-NULL, so if the value is 0, we know we don't have to check this thread's @@ -52,6 +51,10 @@ struct _ceval_runtime_state { struct _gil_runtime_state gil; }; +struct _ceval_state { + int recursion_limit; +}; + /* interpreter state */ #define _PY_NSMALLPOSINTS 257 @@ -75,6 +78,7 @@ struct _is { int finalizing; + struct _ceval_state ceval; struct _gc_runtime_state gc; PyObject *modules; diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst new file mode 100644 index 00000000000000..1ce3acf5bbacc0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst @@ -0,0 +1,3 @@ +subinterpreters: Move ``_PyRuntimeState.ceval.recursion_limit`` to +``PyInterpreterState.ceval.recursion_limit``: make the limit +per-interpreter. diff --git a/Python/ceval.c b/Python/ceval.c index b359fb079841cd..2542cfd5cee713 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -638,26 +638,31 @@ Py_MakePendingCalls(void) int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; void -_PyEval_Initialize(struct _ceval_runtime_state *state) +_PyEval_InitializeRuntime(struct _ceval_runtime_state *ceval) { - state->recursion_limit = Py_DEFAULT_RECURSION_LIMIT; _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; - _gil_initialize(&state->gil); + _gil_initialize(&ceval->gil); +} + +void +_PyEval_InitializeInterp(struct _ceval_state *ceval) +{ + ceval->recursion_limit = Py_DEFAULT_RECURSION_LIMIT; } int Py_GetRecursionLimit(void) { - struct _ceval_runtime_state *ceval = &_PyRuntime.ceval; - return ceval->recursion_limit; + PyThreadState *tstate = _PyThreadState_GET(); + return tstate->interp->ceval.recursion_limit; } void Py_SetRecursionLimit(int new_limit) { - struct _ceval_runtime_state *ceval = &_PyRuntime.ceval; - ceval->recursion_limit = new_limit; - _Py_CheckRecursionLimit = ceval->recursion_limit; + PyThreadState *tstate = _PyThreadState_GET(); + tstate->interp->ceval.recursion_limit = new_limit; + _Py_CheckRecursionLimit = new_limit; } /* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() @@ -668,8 +673,7 @@ Py_SetRecursionLimit(int new_limit) int _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) { - _PyRuntimeState *runtime = tstate->interp->runtime; - int recursion_limit = runtime->ceval.recursion_limit; + int recursion_limit = tstate->interp->ceval.recursion_limit; #ifdef USE_STACKCHECK tstate->stackcheck_counter = 0; diff --git a/Python/pystate.c b/Python/pystate.c index f92c2b4c5e2664..3688352ecb054d 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -58,7 +58,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) runtime->open_code_userdata = open_code_userdata; runtime->audit_hook_head = audit_hook_head; - _PyEval_Initialize(&runtime->ceval); + _PyEval_InitializeRuntime(&runtime->ceval); PyPreConfig_InitPythonConfig(&runtime->preconfig); @@ -213,6 +213,7 @@ PyInterpreterState_New(void) _PyRuntimeState *runtime = &_PyRuntime; interp->runtime = runtime; + _PyEval_InitializeInterp(&interp->ceval); _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config);