tatyana-krasnukha created this revision. tatyana-krasnukha added reviewers: zturner, jingham. tatyana-krasnukha added a project: LLDB. Herald added a subscriber: lldb-commits.
The `InitializePythonRAII` left the GIL locked for other threads when using Python >= 3.7. P.S. I'd appreciate any help in making my comments more understandable and laconical. Repository: rLLDB LLDB https://reviews.llvm.org/D58833 Files: Python/ScriptInterpreterPython.cpp Index: Python/ScriptInterpreterPython.cpp =================================================================== --- Python/ScriptInterpreterPython.cpp +++ Python/ScriptInterpreterPython.cpp @@ -156,7 +156,7 @@ if (m_was_already_initialized) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked", - m_was_already_initialized == PyGILState_UNLOCKED ? "un" : ""); + m_gil_state == PyGILState_UNLOCKED ? "un" : ""); PyGILState_Release(m_gil_state); } else { // We initialized the threads in this function, just unlock the GIL. @@ -180,6 +180,18 @@ } 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. + if (PyGILState_Check()) + return; +#endif + if (PyEval_ThreadsInitialized()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
Index: Python/ScriptInterpreterPython.cpp =================================================================== --- Python/ScriptInterpreterPython.cpp +++ Python/ScriptInterpreterPython.cpp @@ -156,7 +156,7 @@ if (m_was_already_initialized) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked", - m_was_already_initialized == PyGILState_UNLOCKED ? "un" : ""); + m_gil_state == PyGILState_UNLOCKED ? "un" : ""); PyGILState_Release(m_gil_state); } else { // We initialized the threads in this function, just unlock the GIL. @@ -180,6 +180,18 @@ } 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. + if (PyGILState_Check()) + return; +#endif + if (PyEval_ThreadsInitialized()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits