Author: zturner
Date: Tue Oct 20 12:38:49 2015
New Revision: 250838

URL: http://llvm.org/viewvc/llvm-project?rev=250838&view=rev
Log:
Fix potential file i/o problem with python handles.

Modified:
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
    
lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
    lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h

Modified: 
lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp?rev=250838&r1=250837&r2=250838&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp 
(original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp 
Tue Oct 20 12:38:49 2015
@@ -605,6 +605,11 @@ PythonDictionary::CreateStructuredDictio
     return result;
 }
 
+PythonFile::PythonFile()
+    : PythonObject()
+{
+}
+
 PythonFile::PythonFile(File &file, const char *mode)
 {
     Reset(file, mode);

Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h?rev=250838&r1=250837&r2=250838&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h 
(original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h Tue 
Oct 20 12:38:49 2015
@@ -334,6 +334,7 @@ public:
 class PythonFile : public PythonObject
 {
   public:
+    PythonFile();
     PythonFile(File &file, const char *mode);
     PythonFile(const char *path, const char *mode);
     PythonFile(PyRefType type, PyObject *o);

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=250838&r1=250837&r2=250838&view=diff
==============================================================================
--- 
lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp 
(original)
+++ 
lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp 
Tue Oct 20 12:38:49 2015
@@ -612,7 +612,7 @@ ScriptInterpreterPython::EnterSession (u
                 // Flush the file before giving it to python to avoid 
interleaved output.
                 in_file.Flush();
 
-                m_saved_stdin = 
sys_module_dict.GetItemForKey(PythonString("stdin"));
+                m_saved_stdin = 
sys_module_dict.GetItemForKey(PythonString("stdin")).AsType<PythonFile>();
                 // This call can deadlock your process if the file is locked
                 PythonFile new_file(in_file, "r");
                 sys_module_dict.SetItemForKey (PythonString("stdin"), 
new_file);
@@ -626,7 +626,7 @@ ScriptInterpreterPython::EnterSession (u
             // Flush the file before giving it to python to avoid interleaved 
output.
             out_file.Flush();
 
-            m_saved_stdout = 
sys_module_dict.GetItemForKey(PythonString("stdout"));
+            m_saved_stdout = 
sys_module_dict.GetItemForKey(PythonString("stdout")).AsType<PythonFile>();
 
             PythonFile new_file(out_file, "w");
             sys_module_dict.SetItemForKey (PythonString("stdout"), new_file);
@@ -641,7 +641,7 @@ ScriptInterpreterPython::EnterSession (u
             // Flush the file before giving it to python to avoid interleaved 
output.
             err_file.Flush();
 
-            m_saved_stderr = 
sys_module_dict.GetItemForKey(PythonString("stderr"));
+            m_saved_stderr = 
sys_module_dict.GetItemForKey(PythonString("stderr")).AsType<PythonFile>();
 
             PythonFile new_file(err_file, "w");
             sys_module_dict.SetItemForKey (PythonString("stderr"), new_file);
@@ -812,48 +812,55 @@ ScriptInterpreterPython::ExecuteOneLine
         FILE *in_file = input_file_sp->GetFile().GetStream();
         FILE *out_file = output_file_sp->GetFile().GetStream();
         FILE *err_file = error_file_sp->GetFile().GetStream();
-        Locker locker(this,
-                      ScriptInterpreterPython::Locker::AcquireLock |
-                      ScriptInterpreterPython::Locker::InitSession |
-                      (options.GetSetLLDBGlobals() ? 
ScriptInterpreterPython::Locker::InitGlobals : 0) |
-                      ((result && result->GetInteractive()) ? 0: 
Locker::NoSTDIN),
-                      ScriptInterpreterPython::Locker::FreeAcquiredLock |
-                      ScriptInterpreterPython::Locker::TearDownSession,
-                      in_file,
-                      out_file,
-                      err_file);
-        
         bool success = false;
-        
-        // Find the correct script interpreter dictionary in the main module.
-        PythonDictionary &session_dict = GetSessionDictionary ();
-        if (session_dict.IsValid())
         {
-            if (GetEmbeddedInterpreterModuleObjects ())
+            // WARNING!  It's imperative that this RAII scope be as tight as 
possible.  In particular, the
+            // scope must end *before* we try to join the read thread.  The 
reason for this is that a
+            // pre-requisite for joining the read thread is that we close the 
write handle (to break the
+            // pipe and cause it to wake up and exit).  But acquiring the GIL 
as below will redirect Python's
+            // stdio to use this same handle.  If we close the handle while 
Python is still using it, bad
+            // things will happen.
+            Locker locker(this,
+                          ScriptInterpreterPython::Locker::AcquireLock |
+                          ScriptInterpreterPython::Locker::InitSession |
+                          (options.GetSetLLDBGlobals() ? 
ScriptInterpreterPython::Locker::InitGlobals : 0) |
+                          ((result && result->GetInteractive()) ? 0: 
Locker::NoSTDIN),
+                          ScriptInterpreterPython::Locker::FreeAcquiredLock |
+                          ScriptInterpreterPython::Locker::TearDownSession,
+                          in_file,
+                          out_file,
+                          err_file);
+        
+            // Find the correct script interpreter dictionary in the main 
module.
+            PythonDictionary &session_dict = GetSessionDictionary ();
+            if (session_dict.IsValid())
             {
-                if (PyCallable_Check(m_run_one_line_function.get()))
+                if (GetEmbeddedInterpreterModuleObjects ())
                 {
-                    PythonObject pargs(PyRefType::Owned, Py_BuildValue("(Os)", 
session_dict.get(), command));
-                    if (pargs.IsValid())
+                    if (PyCallable_Check(m_run_one_line_function.get()))
                     {
-                        PythonObject return_value(PyRefType::Owned,
-                            PyObject_CallObject(m_run_one_line_function.get(), 
pargs.get()));
-                        if (return_value.IsValid())
-                            success = true;
-                        else if (options.GetMaskoutErrors() && PyErr_Occurred 
())
+                        PythonObject pargs(PyRefType::Owned, 
Py_BuildValue("(Os)", session_dict.get(), command));
+                        if (pargs.IsValid())
                         {
-                            PyErr_Print();
-                            PyErr_Clear();
+                            PythonObject return_value(PyRefType::Owned,
+                                
PyObject_CallObject(m_run_one_line_function.get(), pargs.get()));
+                            if (return_value.IsValid())
+                                success = true;
+                            else if (options.GetMaskoutErrors() && 
PyErr_Occurred ())
+                            {
+                                PyErr_Print();
+                                PyErr_Clear();
+                            }
                         }
                     }
                 }
             }
-        }
 
-        // Flush our output and error file handles
-        ::fflush (out_file);
-        if (out_file != err_file)
-            ::fflush (err_file);
+            // Flush our output and error file handles
+            ::fflush (out_file);
+            if (out_file != err_file)
+                ::fflush (err_file);
+        }
         
         if (join_read_thread)
         {

Modified: 
lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h?rev=250838&r1=250837&r2=250838&view=diff
==============================================================================
--- 
lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h 
(original)
+++ 
lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h 
Tue Oct 20 12:38:49 2015
@@ -570,9 +570,9 @@ protected:
     bool
     GetEmbeddedInterpreterModuleObjects ();
 
-    PythonObject m_saved_stdin;
-    PythonObject m_saved_stdout;
-    PythonObject m_saved_stderr;
+    PythonFile m_saved_stdin;
+    PythonFile m_saved_stdout;
+    PythonFile m_saved_stderr;
     PythonObject m_main_module;
     PythonObject m_lldb_module;
     PythonDictionary m_session_dict;


_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to