bpo-39984: Pass tstate to _PyEval_SignalAsyncExc() (GH-19049)
_PyEval_SignalAsyncExc() and _PyEval_FiniThreads() now expect tstate, instead of ceval.
This commit is contained in:
parent
611836a69a
commit
56bfdebfb1
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue