diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index bcb1bb25a49409..a35e5b803bd08d 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -53,12 +53,19 @@ typedef struct _cframe { } CFrame; typedef struct _err_stackitem { - /* This struct represents an entry on the exception stack, which is a - * per-coroutine state. (Coroutine in the computer science sense, - * including the thread and generators). - * This ensures that the exception state is not impacted by "yields" - * from an except handler. + /* This struct represents a single execution context where we might + * be currently handling an exception. It is a per-coroutine state + * (coroutine in the computer science sense, including the thread + * and generators). + * + * This is used as an entry on the exception stack, where each + * entry indicates if it is currently handling an exception. + * This ensures that the exception state is not impacted + * by "yields" from an except handler. The thread + * always has an entry (the bottom-most one). */ + + /* The exception currently being handled in this context, if any. */ PyObject *exc_value; struct _err_stackitem *previous_item; @@ -112,13 +119,9 @@ struct _ts { PyObject *curexc_value; PyObject *curexc_traceback; - /* The exception currently being handled, if no coroutines/generators - * are present. Always last element on the stack referred to be exc_info. - */ - _PyErr_StackItem exc_state; - - /* Pointer to the top of the stack of the exceptions currently - * being handled */ + /* Pointer to the top of the exception stack for the exceptions + * we may be currently handling. (See _PyErr_StackItem above.) + * This is never NULL. */ _PyErr_StackItem *exc_info; PyObject *dict; /* Stores per-thread state */ @@ -174,13 +177,26 @@ struct _ts { /* Unique thread state id. */ uint64_t id; - CFrame root_cframe; PyTraceInfo trace_info; _PyStackChunk *datastack_chunk; PyObject **datastack_top; PyObject **datastack_limit; /* XXX signal handlers should also be here */ + + /* The following fields are here to avoid allocation during init. + The data is exposed through PyThreadState pointer fields. + These fields should not be accessed directly outside of init. + + All other PyInterpreterState pointer fields are populated when + needed and default to NULL. + */ + + /* The thread's exception stack entry. (Always the last entry.) */ + _PyErr_StackItem _exc_state; + + /* The bottom-most frame on the stack. */ + CFrame _root_cframe; }; diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 20508d4a687475..53d0b5c4549bc1 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -12,9 +12,14 @@ extern "C" { struct pyruntimestate; struct _ceval_runtime_state; +#ifndef Py_DEFAULT_RECURSION_LIMIT +# define Py_DEFAULT_RECURSION_LIMIT 1000 +#endif + #include "pycore_interp.h" // PyInterpreterState.eval_frame #include "pycore_pystate.h" // _PyThreadState_GET() + extern void _Py_FinishPendingCalls(PyThreadState *tstate); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock); diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index e35c696610b94f..78602d11bc838c 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -30,6 +30,8 @@ extern "C" { #define _PyThreadState_INIT \ { \ ._static = 1, \ + .recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \ + .context_ver = 1, \ } diff --git a/Python/ceval.c b/Python/ceval.c index d33cd4e1edb5dd..eed902fc687918 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -737,10 +737,6 @@ Py_MakePendingCalls(void) /* The interpreter's recursion limit */ -#ifndef Py_DEFAULT_RECURSION_LIMIT -# define Py_DEFAULT_RECURSION_LIMIT 1000 -#endif - void _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) { diff --git a/Python/pystate.c b/Python/pystate.c index e6175852c461c8..12cd18039d30ba 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -785,21 +785,19 @@ init_threadstate(PyThreadState *tstate, next->prev = tstate; } tstate->next = next; - tstate->prev = NULL; + assert(tstate->prev == NULL); tstate->thread_id = PyThread_get_thread_ident(); #ifdef PY_HAVE_THREAD_NATIVE_ID tstate->native_thread_id = PyThread_get_thread_native_id(); #endif - tstate->context_ver = 1; - tstate->recursion_limit = interp->ceval.recursion_limit, tstate->recursion_remaining = interp->ceval.recursion_limit, - tstate->exc_info = &tstate->exc_state; + tstate->exc_info = &tstate->_exc_state; - tstate->cframe = &tstate->root_cframe; + tstate->cframe = &tstate->_root_cframe; tstate->datastack_chunk = NULL; tstate->datastack_top = NULL; tstate->datastack_limit = NULL; @@ -1037,10 +1035,10 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->curexc_value); Py_CLEAR(tstate->curexc_traceback); - Py_CLEAR(tstate->exc_state.exc_value); + Py_CLEAR(tstate->_exc_state.exc_value); /* The stack of exception states should contain just this thread. */ - if (verbose && tstate->exc_info != &tstate->exc_state) { + if (verbose && tstate->exc_info != &tstate->_exc_state) { fprintf(stderr, "PyThreadState_Clear: warning: thread still has a generator\n"); } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy