[Lldb-commits] [lldb] [lldb] Setup session when calling Python interfaces (PR #197966)

via lldb-commits lldb-commits at lists.llvm.org
Sat May 16 04:11:40 PDT 2026


https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/197966

>From 34bd4e78f158441a906f157a0210a2cff5254302 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Fri, 15 May 2026 17:59:03 +0200
Subject: [PATCH 1/2] [lldb] Setup session when calling Python interfaces

---
 .../Python/Interfaces/ScriptedPythonInterface.h   | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index 637ca1b2ab1f9..921a8fe715198 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -192,8 +192,9 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
         return create_error("Missing scripting object.");
     }
 
-    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
-                   Locker::FreeLock);
+    Locker py_lock(&m_interpreter,
+                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
+                   Locker::FreeLock | Locker::TearDownSession);
 
     PythonObject result = {};
 
@@ -413,8 +414,9 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
       return ErrorWithMessage<T>(caller_signature, "missing script class name",
                                  error);
 
-    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
-                   Locker::FreeLock);
+    Locker py_lock(&m_interpreter,
+                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
+                   Locker::FreeLock | Locker::TearDownSession);
 
     // Get the interpreter dictionary.
     auto dict =
@@ -508,8 +510,9 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
       return ErrorWithMessage<T>(caller_signature, "python object ill-formed",
                                  error);
 
-    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
-                   Locker::FreeLock);
+    Locker py_lock(&m_interpreter,
+                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
+                   Locker::FreeLock | Locker::TearDownSession);
 
     PythonObject implementor(PyRefType::Borrowed,
                              (PyObject *)m_object_instance_sp->GetValue());

>From 1c7588c36234a6cd6bd8b75499aa3fb77ef5eb91 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Fri, 15 May 2026 22:41:24 +0200
Subject: [PATCH 2/2] refactor: split stdio & globals

---
 .../Interfaces/ScriptedPythonInterface.h      | 12 ++---
 .../Python/ScriptInterpreterPython.cpp        | 54 +++++++++++--------
 .../Python/ScriptInterpreterPythonImpl.h      | 27 +++++++---
 3 files changed, 59 insertions(+), 34 deletions(-)

diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index 921a8fe715198..56ef1db630c34 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -193,8 +193,8 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
     }
 
     Locker py_lock(&m_interpreter,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
-                   Locker::FreeLock | Locker::TearDownSession);
+                   Locker::AcquireLock | Locker::InitStdio | Locker::NoSTDIN,
+                   Locker::FreeLock | Locker::TearDownStdio);
 
     PythonObject result = {};
 
@@ -415,8 +415,8 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
                                  error);
 
     Locker py_lock(&m_interpreter,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
-                   Locker::FreeLock | Locker::TearDownSession);
+                   Locker::AcquireLock | Locker::InitStdio | Locker::NoSTDIN,
+                   Locker::FreeLock | Locker::TearDownStdio);
 
     // Get the interpreter dictionary.
     auto dict =
@@ -511,8 +511,8 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
                                  error);
 
     Locker py_lock(&m_interpreter,
-                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
-                   Locker::FreeLock | Locker::TearDownSession);
+                   Locker::AcquireLock | Locker::InitStdio | Locker::NoSTDIN,
+                   Locker::FreeLock | Locker::TearDownStdio);
 
     PythonObject implementor(PyRefType::Borrowed,
                              (PyObject *)m_object_instance_sp->GetValue());
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 3c002394d8760..daf1acd1e8707 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -322,14 +322,13 @@ void ScriptInterpreterPython::Terminate() {
 ScriptInterpreterPythonImpl::Locker::Locker(
     ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
     uint16_t on_leave, FileSP in, FileSP out, FileSP err)
-    : ScriptInterpreterLocker(),
-      m_teardown_session((on_leave & TearDownSession) == TearDownSession),
+    : ScriptInterpreterLocker(), m_on_leave(on_leave),
       m_python_interpreter(py_interpreter) {
   DoAcquireLock();
-  if ((on_entry & InitSession) == InitSession) {
+  if (on_entry & InitSessionMask) {
     if (!DoInitSession(on_entry, in, out, err)) {
       // Don't teardown the session if we didn't init it.
-      m_teardown_session = false;
+      m_on_leave &= ~TearDownSessionMask;
     }
   }
 }
@@ -370,12 +369,13 @@ bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() {
 bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() {
   if (!m_python_interpreter)
     return false;
-  m_python_interpreter->LeaveSession();
+  m_python_interpreter->LeaveSession(m_on_leave & TearDownGlobals,
+                                     m_on_leave & TearDownStdio);
   return true;
 }
 
 ScriptInterpreterPythonImpl::Locker::~Locker() {
-  if (m_teardown_session)
+  if (m_on_leave & TearDownSessionMask)
     DoTearDownSession();
   DoFreeLock();
 }
@@ -550,21 +550,24 @@ ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) {
   return std::make_shared<ScriptInterpreterPythonImpl>(debugger);
 }
 
-void ScriptInterpreterPythonImpl::LeaveSession() {
+void ScriptInterpreterPythonImpl::LeaveSession(bool clear_globals,
+                                               bool clear_stdio) {
   Log *log = GetLog(LLDBLog::Script);
   if (log)
     log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");
 
-  // Unset the LLDB global variables.
-  RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
-                  "= None; lldb.thread = None; lldb.frame = None");
+  if (clear_globals) {
+    // Unset the LLDB global variables.
+    RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
+                    "= None; lldb.thread = None; lldb.frame = None");
+  }
 
   // checking that we have a valid thread state - since we use our own
   // threading and locking in some (rare) cases during cleanup Python may end
   // up believing we have no thread state and PyImport_AddModule will crash if
   // that is the case - since that seems to only happen when destroying the
   // SBDebugger, we can make do without clearing up stdout and stderr
-  if (PyThreadState_GetDict()) {
+  if (clear_stdio && PyThreadState_GetDict()) {
     PythonDictionary &sys_module_dict = GetSysModuleDictionary();
     if (sys_module_dict.IsValid()) {
       if (m_saved_stdin.IsValid()) {
@@ -639,6 +642,10 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
 
   StreamString run_string;
 
+  assert((on_entry_flags & (Locker::InitGlobals | Locker::InitDebugger)) !=
+             (Locker::InitGlobals | Locker::InitDebugger) &&
+         "InitGlobals and InitDebugger are mutually exclusive");
+
   if (on_entry_flags & Locker::InitGlobals) {
     run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
                       m_dictionary_name.c_str(), m_debugger.GetID());
@@ -650,7 +657,7 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
     run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");
     run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
     run_string.PutCString("')");
-  } else {
+  } else if (on_entry_flags & Locker::InitDebugger) {
     // If we aren't initing the globals, we should still always set the
     // debugger (since that is always unique.)
     run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
@@ -661,11 +668,13 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
     run_string.PutCString("')");
   }
 
-  RunSimpleString(run_string.GetData());
-  run_string.Clear();
+  if (!run_string.Empty()) {
+    RunSimpleString(run_string.GetData());
+    run_string.Clear();
+  }
 
   PythonDictionary &sys_module_dict = GetSysModuleDictionary();
-  if (sys_module_dict.IsValid()) {
+  if ((on_entry_flags & Locker::InitStdio) && sys_module_dict.IsValid()) {
     lldb::FileSP top_in_sp;
     lldb::LockableStreamFileSP top_out_sp, top_err_sp;
     if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
@@ -835,8 +844,9 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine(
       // happen.
       Locker locker(
           this,
-          Locker::AcquireLock | Locker::InitSession |
-              (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
+          Locker::AcquireLock | Locker::InitStdio |
+              (options.GetSetLLDBGlobals() ? Locker::InitGlobals
+                                           : Locker::InitDebugger) |
               ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
           Locker::FreeAcquiredLock | Locker::TearDownSession,
           io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
@@ -962,8 +972,9 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
   ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
 
   Locker locker(this,
-                Locker::AcquireLock | Locker::InitSession |
-                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
+                Locker::AcquireLock | Locker::InitStdio |
+                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals
+                                                 : Locker::InitDebugger) |
                     Locker::NoSTDIN,
                 Locker::FreeAcquiredLock | Locker::TearDownSession,
                 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
@@ -1086,8 +1097,9 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
   ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
 
   Locker locker(this,
-                Locker::AcquireLock | Locker::InitSession |
-                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
+                Locker::AcquireLock | Locker::InitStdio |
+                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals
+                                                 : Locker::InitDebugger) |
                     Locker::NoSTDIN,
                 Locker::FreeAcquiredLock | Locker::TearDownSession,
                 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 863cf27785824..e89cd6da62379 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -305,16 +305,29 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
   public:
     enum OnEntry {
       AcquireLock = 0x0001,
-      InitSession = 0x0002,
-      InitGlobals = 0x0004,
-      NoSTDIN = 0x0008
+      InitStdio = 0x0002,
+      /// Set lldb.debugger. Mutually exclusive with `InitGlobals`.
+      InitDebugger = 0x0004,
+      /// Set lldb.{debugger,target,process,thread,frame}. Mutually exclusive
+      /// with `InitDebugger`.
+      InitGlobals = 0x0008,
+      NoSTDIN = 0x0010,
+
+      InitSession = InitStdio | InitDebugger,
+
+      InitSessionMask = InitStdio | InitDebugger | InitGlobals,
     };
 
     enum OnLeave {
       FreeLock = 0x0001,
       FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
                                  // when calling constructor
-      TearDownSession = 0x0004
+      TearDownGlobals = 0x0004,
+      TearDownStdio = 0x0008,
+
+      TearDownSession = TearDownGlobals | TearDownStdio,
+
+      TearDownSessionMask = TearDownGlobals | TearDownStdio,
     };
 
     Locker(ScriptInterpreterPythonImpl *py_interpreter,
@@ -335,7 +348,7 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
 
     bool DoTearDownSession();
 
-    bool m_teardown_session;
+    uint16_t m_on_leave;
     ScriptInterpreterPythonImpl *m_python_interpreter;
     PyGILState_STATE m_GILState;
   };
@@ -368,7 +381,7 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
   bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
                     lldb::FileSP err);
 
-  void LeaveSession();
+  void LeaveSession(bool clear_globals = true, bool reset_stdio = true);
 
   uint32_t IsExecutingPython() {
     std::lock_guard<std::mutex> guard(m_mutex);
@@ -457,7 +470,7 @@ class IOHandlerPythonInterpreter : public IOHandler {
         ScriptInterpreterPythonImpl::Locker locker(
             m_python,
             ScriptInterpreterPythonImpl::Locker::AcquireLock |
-                ScriptInterpreterPythonImpl::Locker::InitSession |
+                ScriptInterpreterPythonImpl::Locker::InitStdio |
                 ScriptInterpreterPythonImpl::Locker::InitGlobals,
             ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |
                 ScriptInterpreterPythonImpl::Locker::TearDownSession);



More information about the lldb-commits mailing list