[Lldb-commits] [lldb] [lldb] Eliminate InitializePythonRAII::InitializeThreadsPrivate (NFC) (PR #151780)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 1 16:17:20 PDT 2025
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/151780
The behavior of thread initialization changed in Python 3.7. The minimum supported Python version is now 3.8. That means that `PyEval_ThreadsInitialized` always returns true and `PyEval_InitThreads` is never called.
The helper function existed to coordinate initializing the threads and acquiring the GIL, which is no longer necessary. With that, there's no point in having the helper at all. This PR eliminates the function and inlines to GIL acquisition into the caller.
>From 273597c7143684d93ed577e656cd5d605fd9575c Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Fri, 1 Aug 2025 16:12:29 -0700
Subject: [PATCH] [lldb] Eliminate
InitializePythonRAII::InitializeThreadsPrivate (NFC)
The behavior of thread initialization changed in Python 3.7. The minimum
supported Python version is now 3.8. That means that
PyEval_ThreadsInitialized always returns true and PyEval_InitThreads was
never called.
The helper function existed to coordinate initializing the threads and
acquiring the GIL, which is no longer necessary, so there's no point in
having the helper at all. This eliminates the function and inlines to
GIL acquisition into the caller.
---
.../Python/ScriptInterpreterPython.cpp | 51 ++++---------------
1 file changed, 10 insertions(+), 41 deletions(-)
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index ce775690b02bf..34193b5d3ac8b 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -137,7 +137,16 @@ struct InitializePythonRAII {
config.install_signal_handlers = 0;
Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
- InitializeThreadsPrivate();
+
+ // The only case we should go further and acquire the GIL: it is unlocked.
+ if (PyGILState_Check())
+ return;
+
+ m_was_already_initialized = true;
+ m_gil_state = PyGILState_Ensure();
+ LLDB_LOGV(GetLog(LLDBLog::Script),
+ "Ensured PyGILState. Previous state = {0}locked\n",
+ m_gil_state == PyGILState_UNLOCKED ? "un" : "");
}
~InitializePythonRAII() {
@@ -153,46 +162,6 @@ struct InitializePythonRAII {
}
private:
- 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.
-
- // The only case we should go further and acquire the GIL: it is unlocked.
- if (PyGILState_Check())
- return;
-
-// `PyEval_ThreadsInitialized` was deprecated in Python 3.9 and removed in
-// Python 3.13. It has been returning `true` always since Python 3.7.
-#if PY_VERSION_HEX < 0x03090000
- if (PyEval_ThreadsInitialized()) {
-#else
- if (true) {
-#endif
- Log *log = GetLog(LLDBLog::Script);
-
- 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" : "");
-
-// `PyEval_InitThreads` was deprecated in Python 3.9 and removed in
-// Python 3.13.
-#if PY_VERSION_HEX < 0x03090000
- return;
- }
-
- // InitThreads acquires the GIL if it hasn't been called before.
- PyEval_InitThreads();
-#else
- }
-#endif
- }
-
PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
bool m_was_already_initialized = false;
};
More information about the lldb-commits
mailing list