summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-18 18:28:53 (GMT)
committerGitHub <noreply@github.com>2020-03-18 18:28:53 (GMT)
commit8849e5962ba481d5d414b3467a256aba2134b4da (patch)
tree469b2d1023971843ce4e29f88ecbc8503342830f
parent1c60567b9a4c8f77e730de9d22690d8e68d7e5f6 (diff)
downloadcpython-8849e5962ba481d5d414b3467a256aba2134b4da.zip
cpython-8849e5962ba481d5d414b3467a256aba2134b4da.tar.gz
cpython-8849e5962ba481d5d414b3467a256aba2134b4da.tar.bz2
bpo-39984: trip_signal() uses PyGILState_GetThisThreadState() (GH-19061)
bpo-37127, bpo-39984: * trip_signal() and Py_AddPendingCall() now get the current Python thread state using PyGILState_GetThisThreadState() rather than _PyRuntimeState_GetThreadState() to be able to get it even if the GIL is released. * _PyEval_SignalReceived() now expects tstate rather than ceval. * Remove ceval parameter of _PyEval_AddPendingCall(): ceval is now get from tstate parameter.
-rw-r--r--Include/internal/pycore_ceval.h4
-rw-r--r--Modules/signalmodule.c14
-rw-r--r--Python/ceval.c14
3 files changed, 19 insertions, 13 deletions
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 4e5ae17..ccfb9ab 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -19,11 +19,9 @@ 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(PyThreadState *tstate);
-PyAPI_FUNC(void) _PyEval_SignalReceived(
- struct _ceval_runtime_state *ceval);
+PyAPI_FUNC(void) _PyEval_SignalReceived(PyThreadState *tstate);
PyAPI_FUNC(int) _PyEval_AddPendingCall(
PyThreadState *tstate,
- struct _ceval_runtime_state *ceval,
int (*func)(void *),
void *arg);
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate);
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index a197673..1028531 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -259,10 +259,14 @@ trip_signal(int sig_num)
cleared in PyErr_CheckSignals() before .tripped. */
_Py_atomic_store(&is_tripped, 1);
+ /* Get the Python thread state using PyGILState API, since
+ _PyThreadState_GET() returns NULL if the GIL is released.
+ For example, signal.raise_signal() releases the GIL. */
+ PyThreadState *tstate = PyGILState_GetThisThreadState();
+ assert(tstate != NULL);
+
/* Notify ceval.c */
- _PyRuntimeState *runtime = &_PyRuntime;
- PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
- _PyEval_SignalReceived(&runtime->ceval);
+ _PyEval_SignalReceived(tstate);
/* And then write to the wakeup fd *after* setting all the globals and
doing the _PyEval_SignalReceived. We used to write to the wakeup fd
@@ -302,7 +306,7 @@ trip_signal(int sig_num)
{
/* Py_AddPendingCall() isn't signal-safe, but we
still use it for this exceptional case. */
- _PyEval_AddPendingCall(tstate, &runtime->ceval,
+ _PyEval_AddPendingCall(tstate,
report_wakeup_send_error,
(void *)(intptr_t) last_error);
}
@@ -321,7 +325,7 @@ trip_signal(int sig_num)
{
/* Py_AddPendingCall() isn't signal-safe, but we
still use it for this exceptional case. */
- _PyEval_AddPendingCall(tstate, &runtime->ceval,
+ _PyEval_AddPendingCall(tstate,
report_wakeup_write_error,
(void *)(intptr_t)errno);
}
diff --git a/Python/ceval.c b/Python/ceval.c
index 8958e14..2f65ea2 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -436,8 +436,9 @@ PyEval_RestoreThread(PyThreadState *tstate)
*/
void
-_PyEval_SignalReceived(struct _ceval_runtime_state *ceval)
+_PyEval_SignalReceived(PyThreadState *tstate)
{
+ struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
/* bpo-30703: Function called when the C signal handler of Python gets a
signal. We cannot queue a callback using Py_AddPendingCall() since
that function is not async-signal-safe. */
@@ -482,9 +483,9 @@ _pop_pending_call(struct _pending_calls *pending,
int
_PyEval_AddPendingCall(PyThreadState *tstate,
- struct _ceval_runtime_state *ceval,
int (*func)(void *), void *arg)
{
+ struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
struct _pending_calls *pending = &ceval->pending;
PyThread_acquire_lock(pending->lock, WAIT_LOCK);
@@ -511,9 +512,12 @@ _PyEval_AddPendingCall(PyThreadState *tstate,
int
Py_AddPendingCall(int (*func)(void *), void *arg)
{
- _PyRuntimeState *runtime = &_PyRuntime;
- PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
- return _PyEval_AddPendingCall(tstate, &runtime->ceval, func, arg);
+ /* Get the Python thread state using PyGILState API, since
+ _PyThreadState_GET() returns NULL if the GIL is released.
+ Py_AddPendingCall() doesn't require the caller to hold the GIL. */
+ PyThreadState *tstate = PyGILState_GetThisThreadState();
+ assert(tstate != NULL);
+ return _PyEval_AddPendingCall(tstate, func, arg);
}
static int