https://github.com/medismailben created https://github.com/llvm/llvm-project/pull/109440
When running a oneliner script expression, if the script interpreter returned a value, that value would be printed to the debugger standard output straight from the interpreter instead of being propagated back to the command return object, which would then forward it to its output stream. This implies that when evaluating a oneliner script expression (with `SBCommandInterpreter::HandleCommand`), the return value would get printed to stdout, but we would not be able to fetch it from the command return object. This patch solves this issue by extending the default Python `InteractiveConsole` class to keep track of the return value, before include it to the command return object. rdar://132420488 >From 77d1924a105ef60bf2328f7f67302b9d8f026c7a Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani <ism...@bennani.ma> Date: Mon, 19 Aug 2024 21:11:18 -0700 Subject: [PATCH] [lldb/Interpreter] Propagate `script` output back to command return object When running a oneliner script expression, if the script interpreter returned a value, that value would be printed to the debugger standard output straight from the interpreter instead of being propagated back to the command return object, which would then forward it to its output stream. This implies that when evaluating a oneliner script expression (with `SBCommandInterpreter::HandleCommand`), the return value would get printed to stdout, but we would not be able to fetch it from the command return object. This patch solves this issue by extending the default Python `InteractiveConsole` class to keep track of the return value, before include it to the command return object. rdar://132420488 Signed-off-by: Med Ismail Bennani <ism...@bennani.ma> --- .../Interpreter/embedded_interpreter.py | 39 +++++++++++++++++-- .../Python/ScriptInterpreterPython.cpp | 7 +++- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py index a487592ef1aee5..fd5c44d0121fbd 100644 --- a/lldb/source/Interpreter/embedded_interpreter.py +++ b/lldb/source/Interpreter/embedded_interpreter.py @@ -8,6 +8,8 @@ import lldb import traceback +from io import StringIO + try: import readline import rlcompleter @@ -116,19 +118,50 @@ def run_python_interpreter(local_dict): print("Script exited with code %s" % e.code) +class LLDBInteractiveConsole(code.InteractiveConsole): + def __init__(self, locals=None): + super().__init__(locals) + self.result_output = None + + ### Implementation detail: + ### https://docs.python.org/3/library/code.html#code.InteractiveInterpreter.runsource + def runsource(self, source, filename="<input>", symbol="single"): + # Redirect stdout to capture print statements + old_stdout = sys.stdout + sys.stdout = result_output = StringIO() + + try: + compiled_code = self.compile(source, filename, symbol) + if compiled_code is None: + return False + + exec(compiled_code, self.locals) + return True + except Exception as e: + self.showsyntaxerror(filename) + return False + finally: + self.result_output = result_output + sys.stdout = old_stdout + + def get_last_result(self): + return self.result_output.getvalue() + def run_one_line(local_dict, input_string): global g_run_one_line_str try: input_string = strip_and_check_exit(input_string) - repl = code.InteractiveConsole(local_dict) + repl = LLDBInteractiveConsole(local_dict) if input_string: # A newline is appended to support one-line statements containing # control flow. For example "if True: print(1)" silently does # nothing, but works with a newline: "if True: print(1)\n". input_string += "\n" - repl.runsource(input_string) + if repl.runsource(input_string): + return repl.get_last_result() elif g_run_one_line_str: - repl.runsource(g_run_one_line_str) + if repl.runsource(g_run_one_line_str): + return repl.get_last_result() except LLDBExit: pass except SystemExit as e: diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 63691d24f0dadb..30b67ce48a4be9 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -884,9 +884,12 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( PyRefType::Owned, PyObject_CallObject(m_run_one_line_function.get(), pargs.get())); - if (return_value.IsValid()) + if (return_value.IsValid()) { success = true; - else if (options.GetMaskoutErrors() && PyErr_Occurred()) { + PythonString repr = return_value.Repr(); + if (repr && repr.GetSize()) + result->AppendMessage(repr.GetString()); + } else if (options.GetMaskoutErrors() && PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits