mirror of https://github.com/python/cpython
bpo-45953: Statically initialize all the PyThreadState fields we can. (gh-30590)
https://bugs.python.org/issue45953
This commit is contained in:
parent
d4e64cd4b0
commit
324908ba93
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -41,6 +41,8 @@ extern "C" {
|
|||
#define _PyThreadState_INIT \
|
||||
{ \
|
||||
._static = 1, \
|
||||
.recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \
|
||||
.context_ver = 1, \
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -775,21 +775,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;
|
||||
|
@ -1027,10 +1025,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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue