diff options
-rw-r--r-- | Include/internal/pycore_ceval.h | 6 | ||||
-rw-r--r-- | Python/ceval.c | 11 | ||||
-rw-r--r-- | Python/ceval_gil.h | 2 | ||||
-rw-r--r-- | Python/pylifecycle.c | 2 | ||||
-rw-r--r-- | Python/pystate.c | 35 |
5 files changed, 30 insertions, 26 deletions
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 5aeef6c..4e5ae17 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -18,8 +18,7 @@ struct _frame; extern void _Py_FinishPendingCalls(PyThreadState *tstate); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); extern void _PyEval_InitState(struct _ceval_state *); -extern void _PyEval_FiniThreads( - struct _ceval_runtime_state *ceval); +extern void _PyEval_FiniThreads(PyThreadState *tstate); PyAPI_FUNC(void) _PyEval_SignalReceived( struct _ceval_runtime_state *ceval); PyAPI_FUNC(int) _PyEval_AddPendingCall( @@ -27,8 +26,7 @@ PyAPI_FUNC(int) _PyEval_AddPendingCall( struct _ceval_runtime_state *ceval, int (*func)(void *), void *arg); -PyAPI_FUNC(void) _PyEval_SignalAsyncExc( - struct _ceval_runtime_state *ceval); +PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate); PyAPI_FUNC(void) _PyEval_ReInitThreads( struct pyruntimestate *runtime); PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth( diff --git a/Python/ceval.c b/Python/ceval.c index d4c15f3..8958e14 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -246,8 +246,9 @@ PyEval_InitThreads(void) } void -_PyEval_FiniThreads(struct _ceval_runtime_state *ceval) +_PyEval_FiniThreads(PyThreadState *tstate) { + struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _gil_runtime_state *gil = &ceval->gil; if (!gil_created(gil)) { return; @@ -356,10 +357,11 @@ void _PyEval_ReInitThreads(_PyRuntimeState *runtime) { struct _ceval_runtime_state *ceval = &runtime->ceval; - if (!gil_created(&ceval->gil)) { + struct _gil_runtime_state *gil = &runtime->ceval.gil; + if (!gil_created(gil)) { return; } - recreate_gil(&ceval->gil); + recreate_gil(gil); PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); ensure_tstate_not_null(__func__, tstate); @@ -379,8 +381,9 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime) raised. */ void -_PyEval_SignalAsyncExc(struct _ceval_runtime_state *ceval) +_PyEval_SignalAsyncExc(PyThreadState *tstate) { + struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; SIGNAL_ASYNC_EXC(ceval); } diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index f8b06ac..3e9f405 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -286,7 +286,7 @@ _ready: /* Don't access tstate if the thread must exit */ if (!must_exit && tstate->async_exc != NULL) { - _PyEval_SignalAsyncExc(ceval); + _PyEval_SignalAsyncExc(tstate); } MUTEX_UNLOCK(gil->mutex); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index e63ecf7..da2bb37 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -548,7 +548,7 @@ pycore_create_interpreter(_PyRuntimeState *runtime, another running thread (see issue #9901). Instead we destroy the previously created GIL here, which ensures that we can call Py_Initialize / Py_FinalizeEx multiple times. */ - _PyEval_FiniThreads(&runtime->ceval); + _PyEval_FiniThreads(tstate); /* Auto-thread-state API */ status = _PyGILState_Init(tstate); diff --git a/Python/pystate.c b/Python/pystate.c index a349cea..a792cc5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1034,23 +1034,26 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) * head_mutex for the duration. */ HEAD_LOCK(runtime); - for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { - if (p->thread_id == id) { - /* Tricky: we need to decref the current value - * (if any) in p->async_exc, but that can in turn - * allow arbitrary Python code to run, including - * perhaps calls to this function. To prevent - * deadlock, we need to release head_mutex before - * the decref. - */ - PyObject *old_exc = p->async_exc; - Py_XINCREF(exc); - p->async_exc = exc; - HEAD_UNLOCK(runtime); - Py_XDECREF(old_exc); - _PyEval_SignalAsyncExc(&runtime->ceval); - return 1; + for (PyThreadState *tstate = interp->tstate_head; tstate != NULL; tstate = tstate->next) { + if (tstate->thread_id != id) { + continue; } + + /* Tricky: we need to decref the current value + * (if any) in tstate->async_exc, but that can in turn + * allow arbitrary Python code to run, including + * perhaps calls to this function. To prevent + * deadlock, we need to release head_mutex before + * the decref. + */ + PyObject *old_exc = tstate->async_exc; + Py_XINCREF(exc); + tstate->async_exc = exc; + HEAD_UNLOCK(runtime); + + Py_XDECREF(old_exc); + _PyEval_SignalAsyncExc(tstate); + return 1; } HEAD_UNLOCK(runtime); return 0; |