[Python-checkins] bpo-39984: Pass tstate to _PyEval_SignalAsyncExc() (GH-19049)

Victor Stinner webhook-mailer at python.org
Wed Mar 18 04:26:29 EDT 2020


https://github.com/python/cpython/commit/56bfdebfb17ea9d3245b1f222e92b8e3b1ed6118
commit: 56bfdebfb17ea9d3245b1f222e92b8e3b1ed6118
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-03-18T09:26:25+01:00
summary:

bpo-39984: Pass tstate to _PyEval_SignalAsyncExc() (GH-19049)

_PyEval_SignalAsyncExc() and _PyEval_FiniThreads() now expect tstate,
instead of ceval.

files:
M Include/internal/pycore_ceval.h
M Python/ceval.c
M Python/ceval_gil.h
M Python/pylifecycle.c
M Python/pystate.c

diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 5aeef6c755ac5..4e5ae17d63d68 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 d4c15f37c89de..8958e1445db6b 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 f8b06ac68c914..3e9f405f62d79 100644
--- a/Python/ceval_gil.h
+++ b/Python/ceval_gil.h
@@ -286,7 +286,7 @@ take_gil(PyThreadState *tstate)
 
     /* 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 e63ecf70f35c1..da2bb37af518c 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 a349cea7ded0b..a792cc5622d04 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;



More information about the Python-checkins mailing list