summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorJoannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com>2019-04-29 08:38:45 (GMT)
committerVictor Stinner <vstinner@redhat.com>2019-04-29 08:38:45 (GMT)
commitf781d202a2382731b43bade845a58d28a02e9ea1 (patch)
treeb86f74ef510093ef69e73143361afe52e9e7ba46 /Python
parent254b309c801f82509597e3d7d4be56885ef94c11 (diff)
downloadcpython-f781d202a2382731b43bade845a58d28a02e9ea1.zip
cpython-f781d202a2382731b43bade845a58d28a02e9ea1.tar.gz
cpython-f781d202a2382731b43bade845a58d28a02e9ea1.tar.bz2
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().
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 4e165c3..ccd0427 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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");