From 175a704abfcb3400aaeb66d4f098d92ca7e30892 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 10 Mar 2020 00:37:48 +0100 Subject: [PATCH] bpo-39877: PyGILState_Ensure() don't call PyEval_InitThreads() (GH-18891) PyGILState_Ensure() doesn't call PyEval_InitThreads() anymore when a new Python thread state is created. The GIL is created by Py_Initialize() since Python 3.7, it's not needed to call PyEval_InitThreads() explicitly. Add an assertion to ensure that the GIL is already created. --- Include/internal/pycore_ceval.h | 1 + Python/ceval.c | 8 +++++++- Python/pystate.c | 32 +++++++++++++------------------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index b20e85ccb0a..70ce0ee5f70 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -53,6 +53,7 @@ extern PyObject *_PyEval_EvalCode( PyObject *kwdefs, PyObject *closure, PyObject *name, PyObject *qualname); +extern int _PyEval_ThreadsInitialized(_PyRuntimeState *runtime); extern PyStatus _PyEval_InitThreads(PyThreadState *tstate); #ifdef __cplusplus diff --git a/Python/ceval.c b/Python/ceval.c index 72a830468fa..0ee740ace3d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -198,11 +198,17 @@ ensure_tstate_not_null(const char *func, PyThreadState *tstate) } +int +_PyEval_ThreadsInitialized(_PyRuntimeState *runtime) +{ + return gil_created(&runtime->ceval.gil); +} + int PyEval_ThreadsInitialized(void) { _PyRuntimeState *runtime = &_PyRuntime; - return gil_created(&runtime->ceval.gil); + return _PyEval_ThreadsInitialized(runtime); } PyStatus diff --git a/Python/pystate.c b/Python/pystate.c index f907fc1fc9a..a926e9753cb 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1280,27 +1280,28 @@ PyGILState_Check(void) PyGILState_STATE PyGILState_Ensure(void) { - struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; - int current; - PyThreadState *tcur; - int need_init_threads = 0; + _PyRuntimeState *runtime = &_PyRuntime; + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; /* Note that we do not auto-init Python here - apart from potential races with 2 threads auto-initializing, pep-311 spells out other issues. Embedders are expected to have - called Py_Initialize() and usually PyEval_InitThreads(). - */ - /* Py_Initialize() hasn't been called! */ + called Py_Initialize(). */ + + /* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been + called by Py_Initialize() */ + assert(_PyEval_ThreadsInitialized(runtime)); assert(gilstate->autoInterpreterState); - tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); + PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); + int current; if (tcur == NULL) { - need_init_threads = 1; - - /* Create a new thread state for this thread */ + /* Create a new Python thread state for this thread */ tcur = PyThreadState_New(gilstate->autoInterpreterState); - if (tcur == NULL) + if (tcur == NULL) { Py_FatalError("Couldn't create thread-state for new thread"); + } + /* This is our thread state! We'll need to delete it in the matching call to PyGILState_Release(). */ tcur->gilstate_counter = 0; @@ -1321,13 +1322,6 @@ PyGILState_Ensure(void) */ ++tcur->gilstate_counter; - if (need_init_threads) { - /* At startup, Python has no concrete GIL. If PyGILState_Ensure() is - called from a new thread for the first time, we need the create the - GIL. */ - PyEval_InitThreads(); - } - return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; }