[Lldb-commits] [lldb] r374964 - update ScriptInterpreterPython to use File, not FILE*

Lawrence D'Anna via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 15 18:58:15 PDT 2019


Author: lawrence_danna
Date: Tue Oct 15 18:58:15 2019
New Revision: 374964

URL: http://llvm.org/viewvc/llvm-project?rev=374964&view=rev
Log:
update ScriptInterpreterPython to use File, not FILE*

Summary:
ScriptInterpreterPython needs to save and restore sys.stdout and
friends when LLDB runs a python script.

It currently does this using FILE*, which is not optimal.  If
whatever was in sys.stdout can not be represented as a FILE*, then
it will not be restored correctly when the script is finished.

It also means that if the debugger's own output stream is not
representable as a file, ScriptInterpreterPython will not be able
to redirect python's  output correctly.

This patch updates ScriptInterpreterPython to represent files with
lldb_private::File, and to represent whatever the user had in
sys.stdout as simply a PythonObject.

This will make lldb interoperate better with other scripts or programs
that need to manipulate sys.stdout.

Reviewers: JDevlieghere, jasonmolenda, labath

Reviewed By: labath

Subscribers: lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D68962

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h

Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py?rev=374964&r1=374963&r2=374964&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py Tue Oct 15 18:58:15 2019
@@ -445,9 +445,8 @@ class FileHandleTestCase(lldbtest.TestBa
             self.assertTrue(re.search(r'error:.*lolwut', errors))
             self.assertTrue(re.search(r'zork', errors))
 
-    #FIXME This shouldn't fail for python2 either.
+
     @add_test_categories(['pyapi'])
-    @skipIf(py_version=['<', (3,)])
     def test_replace_stdout(self):
         f = io.StringIO()
         with replace_stdout(f):
@@ -458,7 +457,6 @@ class FileHandleTestCase(lldbtest.TestBa
 
 
     @add_test_categories(['pyapi'])
-    @expectedFailureAll() #FIXME bug in ScriptInterpreterPython
     def test_replace_stdout_with_nonfile(self):
         debugger = self.debugger
         f = io.StringIO()

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=374964&r1=374963&r2=374964&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Tue Oct 15 18:58:15 2019
@@ -973,34 +973,31 @@ void Debugger::AdoptTopIOHandlerFilesIfI
   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
   // If no STDIN has been set, then set it appropriately
-  if (!in) {
+  if (!in || !in->IsValid()) {
     if (top_reader_sp)
       in = top_reader_sp->GetInputFileSP();
     else
       in = GetInputFileSP();
-
     // If there is nothing, use stdin
     if (!in)
       in = std::make_shared<NativeFile>(stdin, false);
   }
   // If no STDOUT has been set, then set it appropriately
-  if (!out) {
+  if (!out || !out->GetFile().IsValid()) {
     if (top_reader_sp)
       out = top_reader_sp->GetOutputStreamFileSP();
     else
       out = GetOutputStreamSP();
-
     // If there is nothing, use stdout
     if (!out)
       out = std::make_shared<StreamFile>(stdout, false);
   }
   // If no STDERR has been set, then set it appropriately
-  if (!err) {
+  if (!err || !err->GetFile().IsValid()) {
     if (top_reader_sp)
       err = top_reader_sp->GetErrorStreamFileSP();
     else
       err = GetErrorStreamSP();
-
     // If there is nothing, use stderr
     if (!err)
       err = std::make_shared<StreamFile>(stderr, false);

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp?rev=374964&r1=374963&r2=374964&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp Tue Oct 15 18:58:15 2019
@@ -370,7 +370,7 @@ void ScriptInterpreterPython::Terminate(
 
 ScriptInterpreterPythonImpl::Locker::Locker(
     ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
-    uint16_t on_leave, FILE *in, FILE *out, FILE *err)
+    uint16_t on_leave, FileSP in, FileSP out, FileSP err)
     : ScriptInterpreterLocker(),
       m_teardown_session((on_leave & TearDownSession) == TearDownSession),
       m_python_interpreter(py_interpreter) {
@@ -400,8 +400,8 @@ bool ScriptInterpreterPythonImpl::Locker
 }
 
 bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags,
-                                                        FILE *in, FILE *out,
-                                                        FILE *err) {
+                                                        FileSP in, FileSP out,
+                                                        FileSP err) {
   if (!m_python_interpreter)
     return false;
   return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
@@ -636,28 +636,31 @@ void ScriptInterpreterPythonImpl::LeaveS
   m_session_is_active = false;
 }
 
-bool ScriptInterpreterPythonImpl::SetStdHandle(File &file, const char *py_name,
-                                               PythonFile &save_file,
+bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp,
+                                               const char *py_name,
+                                               PythonObject &save_file,
                                                const char *mode) {
-  if (file.IsValid()) {
-    // Flush the file before giving it to python to avoid interleaved output.
-    file.Flush();
+  if (!file_sp || !*file_sp) {
+    save_file.Reset();
+    return false;
+  }
+  File &file = *file_sp;
 
-    PythonDictionary &sys_module_dict = GetSysModuleDictionary();
+  // Flush the file before giving it to python to avoid interleaved output.
+  file.Flush();
 
-    save_file = sys_module_dict.GetItemForKey(PythonString(py_name))
-                    .AsType<PythonFile>();
+  PythonDictionary &sys_module_dict = GetSysModuleDictionary();
 
-    PythonFile new_file(file, mode);
-    sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
-    return true;
-  } else
-    save_file.Reset();
-  return false;
+  save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
+
+  PythonFile new_file(file, mode);
+  sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
+  return true;
 }
 
 bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
-                                               FILE *in, FILE *out, FILE *err) {
+                                               FileSP in_sp, FileSP out_sp,
+                                               FileSP err_sp) {
   // If we have already entered the session, without having officially 'left'
   // it, then there is no need to 'enter' it again.
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
@@ -706,33 +709,29 @@ bool ScriptInterpreterPythonImpl::EnterS
 
   PythonDictionary &sys_module_dict = GetSysModuleDictionary();
   if (sys_module_dict.IsValid()) {
-    NativeFile in_file(in, false);
-    NativeFile out_file(out, false);
-    NativeFile err_file(err, false);
-
-    lldb::FileSP in_sp;
-    lldb::StreamFileSP out_sp;
-    lldb::StreamFileSP err_sp;
-    if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
-      m_debugger.AdoptTopIOHandlerFilesIfInvalid(in_sp, out_sp, err_sp);
+    lldb::FileSP top_in_sp;
+    lldb::StreamFileSP top_out_sp, top_err_sp;
+    if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
+      m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,
+                                                 top_err_sp);
 
     if (on_entry_flags & Locker::NoSTDIN) {
       m_saved_stdin.Reset();
     } else {
-      if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) {
-        if (in_sp)
-          SetStdHandle(*in_sp, "stdin", m_saved_stdin, "r");
+      if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r")) {
+        if (top_in_sp)
+          SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r");
       }
     }
 
-    if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) {
-      if (out_sp)
-        SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w");
+    if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) {
+      if (top_out_sp)
+        SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w");
     }
 
-    if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) {
-      if (err_sp)
-        SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w");
+    if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) {
+      if (top_err_sp)
+        SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w");
     }
   }
 
@@ -909,9 +908,6 @@ bool ScriptInterpreterPythonImpl::Execut
       error_file_sp = output_file_sp = std::make_shared<StreamFile>(std::move(nullout.get()));
     }
 
-    FILE *in_file = input_file_sp->GetStream();
-    FILE *out_file = output_file_sp->GetFile().GetStream();
-    FILE *err_file = error_file_sp->GetFile().GetStream();
     bool success = false;
     {
       // WARNING!  It's imperative that this RAII scope be as tight as
@@ -927,8 +923,8 @@ bool ScriptInterpreterPythonImpl::Execut
           Locker::AcquireLock | Locker::InitSession |
               (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
               ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
-          Locker::FreeAcquiredLock | Locker::TearDownSession, in_file, out_file,
-          err_file);
+          Locker::FreeAcquiredLock | Locker::TearDownSession, input_file_sp,
+          output_file_sp->GetFileSP(), error_file_sp->GetFileSP());
 
       // Find the correct script interpreter dictionary in the main module.
       PythonDictionary &session_dict = GetSessionDictionary();
@@ -955,9 +951,8 @@ bool ScriptInterpreterPythonImpl::Execut
       }
 
       // Flush our output and error file handles
-      ::fflush(out_file);
-      if (out_file != err_file)
-        ::fflush(err_file);
+      output_file_sp->Flush();
+      error_file_sp->Flush();
     }
 
     if (join_read_thread) {

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h?rev=374964&r1=374963&r2=374964&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h Tue Oct 15 18:58:15 2019
@@ -294,17 +294,19 @@ public:
       TearDownSession = 0x0004
     };
 
-    Locker(ScriptInterpreterPythonImpl *py_interpreter = nullptr,
+    Locker(ScriptInterpreterPythonImpl *py_interpreter,
            uint16_t on_entry = AcquireLock | InitSession,
-           uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr,
-           FILE *out = nullptr, FILE *err = nullptr);
+           uint16_t on_leave = FreeLock | TearDownSession,
+           lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,
+           lldb::FileSP err = nullptr);
 
     ~Locker() override;
 
   private:
     bool DoAcquireLock();
 
-    bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
+    bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
+                       lldb::FileSP out, lldb::FileSP err);
 
     bool DoFreeLock();
 
@@ -312,7 +314,6 @@ public:
 
     bool m_teardown_session;
     ScriptInterpreterPythonImpl *m_python_interpreter;
-    //    	FILE*                    m_tmp_fh;
     PyGILState_STATE m_GILState;
   };
 
@@ -341,7 +342,8 @@ public:
 
   static void AddToSysPath(AddLocation location, std::string path);
 
-  bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
+  bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
+                    lldb::FileSP err);
 
   void LeaveSession();
 
@@ -369,12 +371,12 @@ public:
 
   bool GetEmbeddedInterpreterModuleObjects();
 
-  bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file,
-                    const char *mode);
+  bool SetStdHandle(lldb::FileSP file, const char *py_name,
+                    PythonObject &save_file, const char *mode);
 
-  PythonFile m_saved_stdin;
-  PythonFile m_saved_stdout;
-  PythonFile m_saved_stderr;
+  PythonObject m_saved_stdin;
+  PythonObject m_saved_stdout;
+  PythonObject m_saved_stderr;
   PythonObject m_main_module;
   PythonDictionary m_session_dict;
   PythonDictionary m_sys_module_dict;




More information about the lldb-commits mailing list