Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -328,31 +328,45 @@ #endif } - void InitializeThreadsPrivate() { -// Since Python 3.7 `Py_Initialize` calls `PyEval_InitThreads` inside itself, -// so there is no way to determine whether the embedded interpreter -// was already initialized by some external code. `PyEval_ThreadsInitialized` -// would always return `true` and `PyGILState_Ensure/Release` flow would be -// executed instead of unlocking GIL with `PyEval_SaveThread`. When -// an another thread calls `PyGILState_Ensure` it would get stuck in deadlock. -#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION > 3) - // The only case we should go further and acquire the GIL: it is unlocked. + /// Acquires the GIL if it hasn't already been acquired by someone else. + void EnsureGIL() { + // If this thread already holds the GIL then there is nothing to initialize + // or set up. if (PyGILState_Check()) return; -#endif + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); + // Acquire the GIL. + m_was_already_initialized = true; + m_gil_state = PyGILState_Ensure(); + LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n", + m_gil_state == PyGILState_UNLOCKED ? "un" : ""); + } - if (PyEval_ThreadsInitialized()) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); + /// Initializes Python's threading support if needed and acquires the GIL. + void InitializeThreadsPrivate() { + // With Python 3.9 PyEval_InitThreads does nothing and is marked as + // deprecated. With Python 3.11 the function also got removed. + // PyEval_InitThreads is always called from Py_Initialize/Py_InitializeEx + // since Python 3.7 so we don't need to call it manually. - m_was_already_initialized = true; - m_gil_state = PyGILState_Ensure(); - LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n", - m_gil_state == PyGILState_UNLOCKED ? "un" : ""); + // The only thing we need to do for Python>=3.7 is to acquire the GIL as + // that's we promised the caller of this function. +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION > 3) + EnsureGIL(); +#else + // For Python<3.7 call PyEval_InitThreads if this hasn't already done + // before by someone else (as indicated by PyEval_ThreadsInitialized). + // Manually try to take the GIL so that we fulfill our contract with the + // caller in case threading support has already been initialized. + if (PyEval_ThreadsInitialized()) { + EnsureGIL(); return; } - // InitThreads acquires the GIL if it hasn't been called before. + // InitThreads acquires the GIL if it hasn't been called before so no + // need to manually acquire it. PyEval_InitThreads(); +#endif } TerminalState m_stdin_tty_state;