bpo-40082: trip_signal() uses the main interpreter (GH-19441)

Fix the signal handler: it now always uses the main interpreter,
rather than trying to get the current Python thread state.

The following function now accepts an interpreter, instead of a
Python thread state:

* _PyEval_SignalReceived()
* _Py_ThreadCanHandleSignals()
* _PyEval_AddPendingCall()
* COMPUTE_EVAL_BREAKER()
* SET_GIL_DROP_REQUEST(), RESET_GIL_DROP_REQUEST()
* SIGNAL_PENDING_CALLS(), UNSIGNAL_PENDING_CALLS()
* SIGNAL_PENDING_SIGNALS(), UNSIGNAL_PENDING_SIGNALS()
* SIGNAL_ASYNC_EXC(), UNSIGNAL_ASYNC_EXC()

Py_AddPendingCall() now uses the main interpreter if it fails to the
current Python thread state.

Convert _PyThreadState_GET() and PyInterpreterState_GET_UNSAFE()
macros to static inline functions.
This commit is contained in:
Victor Stinner 2020-04-08 23:35:05 +02:00 committed by GitHub
parent cfc3c2f8b3
commit b54a99d643
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 85 deletions

View File

@ -19,9 +19,9 @@ extern void _Py_FinishPendingCalls(PyThreadState *tstate);
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
extern int _PyEval_InitState(struct _ceval_state *ceval); extern int _PyEval_InitState(struct _ceval_state *ceval);
extern void _PyEval_FiniState(struct _ceval_state *ceval); extern void _PyEval_FiniState(struct _ceval_state *ceval);
PyAPI_FUNC(void) _PyEval_SignalReceived(PyThreadState *tstate); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp);
PyAPI_FUNC(int) _PyEval_AddPendingCall( PyAPI_FUNC(int) _PyEval_AddPendingCall(
PyThreadState *tstate, PyInterpreterState *interp,
int (*func)(void *), int (*func)(void *),
void *arg); void *arg);
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate); PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate);

View File

@ -310,9 +310,9 @@ _Py_IsMainInterpreter(PyThreadState* tstate)
/* Only handle signals on the main thread of the main interpreter. */ /* Only handle signals on the main thread of the main interpreter. */
static inline int static inline int
_Py_ThreadCanHandleSignals(PyThreadState *tstate) _Py_ThreadCanHandleSignals(PyInterpreterState *interp)
{ {
return (_Py_IsMainThread() && _Py_IsMainInterpreter(tstate)); return (_Py_IsMainThread() && interp == _PyRuntime.interpreters.main);
} }
@ -340,7 +340,9 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run
The caller must hold the GIL. The caller must hold the GIL.
See also PyThreadState_Get() and PyThreadState_GET(). */ See also PyThreadState_Get() and PyThreadState_GET(). */
#define _PyThreadState_GET() _PyRuntimeState_GetThreadState(&_PyRuntime) static inline PyThreadState *_PyThreadState_GET(void) {
return _PyRuntimeState_GetThreadState(&_PyRuntime);
}
/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */ /* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
#undef PyThreadState_GET #undef PyThreadState_GET
@ -354,7 +356,10 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run
See also _PyInterpreterState_Get() See also _PyInterpreterState_Get()
and _PyGILState_GetInterpreterStateUnsafe(). */ and _PyGILState_GetInterpreterStateUnsafe(). */
#define _PyInterpreterState_GET_UNSAFE() (_PyThreadState_GET()->interp) static inline PyInterpreterState* _PyInterpreterState_GET_UNSAFE(void) {
PyThreadState *tstate = _PyThreadState_GET();
return tstate->interp;
}
/* Other */ /* Other */

View File

@ -0,0 +1,2 @@
Fix the signal handler: it now always uses the main interpreter, rather than
trying to get the current Python thread state.

View File

@ -252,14 +252,11 @@ trip_signal(int sig_num)
cleared in PyErr_CheckSignals() before .tripped. */ cleared in PyErr_CheckSignals() before .tripped. */
_Py_atomic_store(&is_tripped, 1); _Py_atomic_store(&is_tripped, 1);
/* Get the Python thread state using PyGILState API, since /* Signals are always handled by the main interpreter */
_PyThreadState_GET() returns NULL if the GIL is released. PyInterpreterState *interp = _PyRuntime.interpreters.main;
For example, signal.raise_signal() releases the GIL. */
PyThreadState *tstate = PyGILState_GetThisThreadState();
assert(tstate != NULL);
/* Notify ceval.c */ /* Notify ceval.c */
_PyEval_SignalReceived(tstate); _PyEval_SignalReceived(interp);
/* And then write to the wakeup fd *after* setting all the globals and /* 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 doing the _PyEval_SignalReceived. We used to write to the wakeup fd
@ -299,7 +296,7 @@ trip_signal(int sig_num)
{ {
/* _PyEval_AddPendingCall() isn't signal-safe, but we /* _PyEval_AddPendingCall() isn't signal-safe, but we
still use it for this exceptional case. */ still use it for this exceptional case. */
_PyEval_AddPendingCall(tstate, _PyEval_AddPendingCall(interp,
report_wakeup_send_error, report_wakeup_send_error,
(void *)(intptr_t) last_error); (void *)(intptr_t) last_error);
} }
@ -318,7 +315,7 @@ trip_signal(int sig_num)
{ {
/* _PyEval_AddPendingCall() isn't signal-safe, but we /* _PyEval_AddPendingCall() isn't signal-safe, but we
still use it for this exceptional case. */ still use it for this exceptional case. */
_PyEval_AddPendingCall(tstate, _PyEval_AddPendingCall(interp,
report_wakeup_write_error, report_wakeup_write_error,
(void *)(intptr_t)errno); (void *)(intptr_t)errno);
} }
@ -476,7 +473,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
#endif #endif
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) { if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
_PyErr_SetString(tstate, PyExc_ValueError, _PyErr_SetString(tstate, PyExc_ValueError,
"signal only works in main thread " "signal only works in main thread "
"of the main interpreter"); "of the main interpreter");
@ -704,7 +701,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds)
#endif #endif
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) { if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
_PyErr_SetString(tstate, PyExc_ValueError, _PyErr_SetString(tstate, PyExc_ValueError,
"set_wakeup_fd only works in main thread " "set_wakeup_fd only works in main thread "
"of the main interpreter"); "of the main interpreter");
@ -1681,7 +1678,7 @@ int
PyErr_CheckSignals(void) PyErr_CheckSignals(void)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) { if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
return 0; return 0;
} }
@ -1787,8 +1784,8 @@ PyOS_FiniInterrupts(void)
int int
PyOS_InterruptOccurred(void) PyOS_InterruptOccurred(void)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
if (!_Py_ThreadCanHandleSignals(tstate)) { if (!_Py_ThreadCanHandleSignals(interp)) {
return 0; return 0;
} }
@ -1824,8 +1821,8 @@ _PySignal_AfterFork(void)
int int
_PyOS_IsMainThread(void) _PyOS_IsMainThread(void)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
return _Py_ThreadCanHandleSignals(tstate); return _Py_ThreadCanHandleSignals(interp);
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS

View File

@ -142,15 +142,14 @@ is_tstate_valid(PyThreadState *tstate)
1. We believe this is all right because the eval loop will release 1. We believe this is all right because the eval loop will release
the GIL eventually anyway. */ the GIL eventually anyway. */
static inline void static inline void
COMPUTE_EVAL_BREAKER(PyThreadState *tstate, COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
struct _ceval_runtime_state *ceval, struct _ceval_runtime_state *ceval,
struct _ceval_state *ceval2) struct _ceval_state *ceval2)
{ {
assert(is_tstate_valid(tstate));
_Py_atomic_store_relaxed(&ceval2->eval_breaker, _Py_atomic_store_relaxed(&ceval2->eval_breaker,
_Py_atomic_load_relaxed(&ceval->gil_drop_request) _Py_atomic_load_relaxed(&ceval->gil_drop_request)
| (_Py_atomic_load_relaxed(&ceval->signals_pending) | (_Py_atomic_load_relaxed(&ceval->signals_pending)
&& _Py_ThreadCanHandleSignals(tstate)) && _Py_ThreadCanHandleSignals(interp))
| (_Py_atomic_load_relaxed(&ceval2->pending.calls_to_do) | (_Py_atomic_load_relaxed(&ceval2->pending.calls_to_do)
&& _Py_ThreadCanHandlePendingCalls()) && _Py_ThreadCanHandlePendingCalls())
| ceval2->pending.async_exc); | ceval2->pending.async_exc);
@ -158,90 +157,82 @@ COMPUTE_EVAL_BREAKER(PyThreadState *tstate,
static inline void static inline void
SET_GIL_DROP_REQUEST(PyThreadState *tstate) SET_GIL_DROP_REQUEST(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval->gil_drop_request, 1); _Py_atomic_store_relaxed(&ceval->gil_drop_request, 1);
_Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
} }
static inline void static inline void
RESET_GIL_DROP_REQUEST(PyThreadState *tstate) RESET_GIL_DROP_REQUEST(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval->gil_drop_request, 0); _Py_atomic_store_relaxed(&ceval->gil_drop_request, 0);
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
static inline void static inline void
SIGNAL_PENDING_CALLS(PyThreadState *tstate) SIGNAL_PENDING_CALLS(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1); _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
static inline void static inline void
UNSIGNAL_PENDING_CALLS(PyThreadState *tstate) UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0); _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0);
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
static inline void static inline void
SIGNAL_PENDING_SIGNALS(PyThreadState *tstate) SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval->signals_pending, 1); _Py_atomic_store_relaxed(&ceval->signals_pending, 1);
/* eval_breaker is not set to 1 if thread_can_handle_signals() is false */ /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
static inline void static inline void
UNSIGNAL_PENDING_SIGNALS(PyThreadState *tstate) UNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval->signals_pending, 0); _Py_atomic_store_relaxed(&ceval->signals_pending, 0);
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
static inline void static inline void
SIGNAL_ASYNC_EXC(PyThreadState *tstate) SIGNAL_ASYNC_EXC(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
ceval2->pending.async_exc = 1; ceval2->pending.async_exc = 1;
_Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
} }
static inline void static inline void
UNSIGNAL_ASYNC_EXC(PyThreadState *tstate) UNSIGNAL_ASYNC_EXC(PyInterpreterState *interp)
{ {
assert(is_tstate_valid(tstate)); struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval2 = &interp->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
ceval2->pending.async_exc = 0; ceval2->pending.async_exc = 0;
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
@ -440,7 +431,8 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime)
void void
_PyEval_SignalAsyncExc(PyThreadState *tstate) _PyEval_SignalAsyncExc(PyThreadState *tstate)
{ {
SIGNAL_ASYNC_EXC(tstate); assert(is_tstate_valid(tstate));
SIGNAL_ASYNC_EXC(tstate->interp);
} }
PyThreadState * PyThreadState *
@ -492,12 +484,12 @@ PyEval_RestoreThread(PyThreadState *tstate)
*/ */
void void
_PyEval_SignalReceived(PyThreadState *tstate) _PyEval_SignalReceived(PyInterpreterState *interp)
{ {
/* bpo-30703: Function called when the C signal handler of Python gets a /* bpo-30703: Function called when the C signal handler of Python gets a
signal. We cannot queue a callback using _PyEval_AddPendingCall() since signal. We cannot queue a callback using _PyEval_AddPendingCall() since
that function is not async-signal-safe. */ that function is not async-signal-safe. */
SIGNAL_PENDING_SIGNALS(tstate); SIGNAL_PENDING_SIGNALS(interp);
} }
/* Push one item onto the queue while holding the lock. */ /* Push one item onto the queue while holding the lock. */
@ -537,10 +529,10 @@ _pop_pending_call(struct _pending_calls *pending,
*/ */
int int
_PyEval_AddPendingCall(PyThreadState *tstate, _PyEval_AddPendingCall(PyInterpreterState *interp,
int (*func)(void *), void *arg) int (*func)(void *), void *arg)
{ {
struct _pending_calls *pending = &tstate->interp->ceval.pending; struct _pending_calls *pending = &interp->ceval.pending;
/* Ensure that _PyEval_InitPendingCalls() was called /* Ensure that _PyEval_InitPendingCalls() was called
and that _PyEval_FiniPendingCalls() is not called yet. */ and that _PyEval_FiniPendingCalls() is not called yet. */
@ -551,7 +543,7 @@ _PyEval_AddPendingCall(PyThreadState *tstate,
PyThread_release_lock(pending->lock); PyThread_release_lock(pending->lock);
/* signal main loop */ /* signal main loop */
SIGNAL_PENDING_CALLS(tstate); SIGNAL_PENDING_CALLS(interp);
return result; return result;
} }
@ -574,24 +566,30 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
if (tstate == NULL) { if (tstate == NULL) {
tstate = PyGILState_GetThisThreadState(); tstate = PyGILState_GetThisThreadState();
} }
/* tstate can be NULL if Py_AddPendingCall() is called in a thread
which is no Python thread state. Fail with a fatal error in this PyInterpreterState *interp;
case. */ if (tstate != NULL) {
ensure_tstate_not_null(__func__, tstate); interp = tstate->interp;
return _PyEval_AddPendingCall(tstate, func, arg); }
else {
/* Last resort: use the main interpreter */
interp = _PyRuntime.interpreters.main;
}
return _PyEval_AddPendingCall(interp, func, arg);
} }
static int static int
handle_signals(PyThreadState *tstate) handle_signals(PyThreadState *tstate)
{ {
if (!_Py_ThreadCanHandleSignals(tstate)) { assert(is_tstate_valid(tstate));
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
return 0; return 0;
} }
UNSIGNAL_PENDING_SIGNALS(tstate); UNSIGNAL_PENDING_SIGNALS(tstate->interp);
if (_PyErr_CheckSignalsTstate(tstate) < 0) { if (_PyErr_CheckSignalsTstate(tstate) < 0) {
/* On failure, re-schedule a call to handle_signals(). */ /* On failure, re-schedule a call to handle_signals(). */
SIGNAL_PENDING_SIGNALS(tstate); SIGNAL_PENDING_SIGNALS(tstate->interp);
return -1; return -1;
} }
return 0; return 0;
@ -600,6 +598,8 @@ handle_signals(PyThreadState *tstate)
static int static int
make_pending_calls(PyThreadState *tstate) make_pending_calls(PyThreadState *tstate)
{ {
assert(is_tstate_valid(tstate));
/* only execute pending calls on main thread */ /* only execute pending calls on main thread */
if (!_Py_ThreadCanHandlePendingCalls()) { if (!_Py_ThreadCanHandlePendingCalls()) {
return 0; return 0;
@ -614,7 +614,7 @@ make_pending_calls(PyThreadState *tstate)
/* unsignal before starting to call callbacks, so that any callback /* unsignal before starting to call callbacks, so that any callback
added in-between re-signals */ added in-between re-signals */
UNSIGNAL_PENDING_CALLS(tstate); UNSIGNAL_PENDING_CALLS(tstate->interp);
int res = 0; int res = 0;
/* perform a bounded number of calls, in case of recursion */ /* perform a bounded number of calls, in case of recursion */
@ -643,7 +643,7 @@ make_pending_calls(PyThreadState *tstate)
error: error:
busy = 0; busy = 0;
SIGNAL_PENDING_CALLS(tstate); SIGNAL_PENDING_CALLS(tstate->interp);
return res; return res;
} }
@ -828,9 +828,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
static int static int
eval_frame_handle_pending(PyThreadState *tstate) eval_frame_handle_pending(PyThreadState *tstate)
{ {
/* Pending signals */
_PyRuntimeState * const runtime = &_PyRuntime; _PyRuntimeState * const runtime = &_PyRuntime;
struct _ceval_runtime_state *ceval = &runtime->ceval; struct _ceval_runtime_state *ceval = &runtime->ceval;
/* Pending signals */
if (_Py_atomic_load_relaxed(&ceval->signals_pending)) { if (_Py_atomic_load_relaxed(&ceval->signals_pending)) {
if (handle_signals(tstate) != 0) { if (handle_signals(tstate) != 0) {
return -1; return -1;
@ -866,7 +867,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
if (tstate->async_exc != NULL) { if (tstate->async_exc != NULL) {
PyObject *exc = tstate->async_exc; PyObject *exc = tstate->async_exc;
tstate->async_exc = NULL; tstate->async_exc = NULL;
UNSIGNAL_ASYNC_EXC(tstate); UNSIGNAL_ASYNC_EXC(tstate->interp);
_PyErr_SetNone(tstate, exc); _PyErr_SetNone(tstate, exc);
Py_DECREF(exc); Py_DECREF(exc);
return -1; return -1;

View File

@ -168,7 +168,8 @@ drop_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate)
/* Not switched yet => wait */ /* Not switched yet => wait */
if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate) if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate)
{ {
RESET_GIL_DROP_REQUEST(tstate); assert(is_tstate_valid(tstate));
RESET_GIL_DROP_REQUEST(tstate->interp);
/* NOTE: if COND_WAIT does not atomically start waiting when /* NOTE: if COND_WAIT does not atomically start waiting when
releasing the mutex, another thread can run through, take releasing the mutex, another thread can run through, take
the GIL and drop it again, and reset the condition the GIL and drop it again, and reset the condition
@ -223,7 +224,8 @@ take_gil(PyThreadState *tstate)
} }
assert(is_tstate_valid(tstate)); assert(is_tstate_valid(tstate));
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; PyInterpreterState *interp = tstate->interp;
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _gil_runtime_state *gil = &ceval->gil; struct _gil_runtime_state *gil = &ceval->gil;
/* Check that _PyEval_InitThreads() was called to create the lock */ /* Check that _PyEval_InitThreads() was called to create the lock */
@ -252,8 +254,9 @@ take_gil(PyThreadState *tstate)
MUTEX_UNLOCK(gil->mutex); MUTEX_UNLOCK(gil->mutex);
PyThread_exit_thread(); PyThread_exit_thread();
} }
assert(is_tstate_valid(tstate));
SET_GIL_DROP_REQUEST(tstate); SET_GIL_DROP_REQUEST(interp);
} }
} }
@ -289,9 +292,10 @@ take_gil(PyThreadState *tstate)
drop_gil(ceval, tstate); drop_gil(ceval, tstate);
PyThread_exit_thread(); PyThread_exit_thread();
} }
assert(is_tstate_valid(tstate));
if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) { if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) {
RESET_GIL_DROP_REQUEST(tstate); RESET_GIL_DROP_REQUEST(interp);
} }
else { else {
/* bpo-40010: eval_breaker should be recomputed to be set to 1 if there /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there
@ -299,8 +303,8 @@ take_gil(PyThreadState *tstate)
handle signals. handle signals.
Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */ Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */
struct _ceval_state *ceval2 = &tstate->interp->ceval; struct _ceval_state *ceval2 = &interp->ceval;
COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2); COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
} }
/* Don't access tstate if the thread must exit */ /* Don't access tstate if the thread must exit */