mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-36475: Finalize PyEval_AcquireLock() and PyEval_AcquireThread() properly (GH-12667)
PyEval_AcquireLock() and PyEval_AcquireThread() now terminate the current thread if called while the interpreter is finalizing, making them consistent with PyEval_RestoreThread(), Py_END_ALLOW_THREADS, and PyGILState_Ensure().
This commit is contained in:
parent
254b309c80
commit
f781d202a2
4 changed files with 51 additions and 12 deletions
|
@ -76,6 +76,7 @@ static PyObject * special_lookup(PyObject *, _Py_Identifier *);
|
|||
static int check_args_iterable(PyObject *func, PyObject *vararg);
|
||||
static void format_kwargs_error(PyObject *func, PyObject *kwargs);
|
||||
static void format_awaitable_error(PyTypeObject *, int);
|
||||
static inline void exit_thread_if_finalizing(PyThreadState *);
|
||||
|
||||
#define NAME_ERROR_MSG \
|
||||
"name '%.200s' is not defined"
|
||||
|
@ -203,6 +204,17 @@ _PyEval_FiniThreads(void)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
exit_thread_if_finalizing(PyThreadState *tstate)
|
||||
{
|
||||
/* _Py_Finalizing is protected by the GIL */
|
||||
if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) {
|
||||
drop_gil(tstate);
|
||||
PyThread_exit_thread();
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PyEval_AcquireLock(void)
|
||||
{
|
||||
|
@ -210,6 +222,7 @@ PyEval_AcquireLock(void)
|
|||
if (tstate == NULL)
|
||||
Py_FatalError("PyEval_AcquireLock: current thread state is NULL");
|
||||
take_gil(tstate);
|
||||
exit_thread_if_finalizing(tstate);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -230,6 +243,7 @@ PyEval_AcquireThread(PyThreadState *tstate)
|
|||
/* Check someone has called PyEval_InitThreads() to create the lock */
|
||||
assert(gil_created());
|
||||
take_gil(tstate);
|
||||
exit_thread_if_finalizing(tstate);
|
||||
if (PyThreadState_Swap(tstate) != NULL)
|
||||
Py_FatalError(
|
||||
"PyEval_AcquireThread: non-NULL old thread state");
|
||||
|
@ -298,12 +312,7 @@ PyEval_RestoreThread(PyThreadState *tstate)
|
|||
|
||||
int err = errno;
|
||||
take_gil(tstate);
|
||||
/* _Py_Finalizing is protected by the GIL */
|
||||
if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) {
|
||||
drop_gil(tstate);
|
||||
PyThread_exit_thread();
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
exit_thread_if_finalizing(tstate);
|
||||
errno = err;
|
||||
|
||||
PyThreadState_Swap(tstate);
|
||||
|
@ -1083,12 +1092,7 @@ main_loop:
|
|||
take_gil(tstate);
|
||||
|
||||
/* Check if we should make a quick exit. */
|
||||
if (_Py_IsFinalizing() &&
|
||||
!_Py_CURRENTLY_FINALIZING(tstate))
|
||||
{
|
||||
drop_gil(tstate);
|
||||
PyThread_exit_thread();
|
||||
}
|
||||
exit_thread_if_finalizing(tstate);
|
||||
|
||||
if (PyThreadState_Swap(tstate) != NULL)
|
||||
Py_FatalError("ceval: orphan tstate");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue