Add proper EOF handling to Communication & Connection classes:

Add bool member to Communication class indicating whether the
Connection should be closed on receiving an EOF or not.  Update the
Connection read to return an EOF status when appropriate.  Modify the
Communication class to pass the EOF along or not, and to close the
Connection or not, as appropriate.




git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@120723 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBCommunication.cpp b/source/API/SBCommunication.cpp
index ac3042f..6aa1e24 100644
--- a/source/API/SBCommunication.cpp
+++ b/source/API/SBCommunication.cpp
@@ -24,8 +24,8 @@
 {
 }
 
-SBCommunication::SBCommunication(const char * broadcaster_name) :
-    m_opaque (new Communication (broadcaster_name)),
+SBCommunication::SBCommunication(const char * broadcaster_name, bool close_on_eof) :
+    m_opaque (new Communication (broadcaster_name, close_on_eof)),
     m_opaque_owned (true)
 {
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
index 17ed2fd..f8de198 100644
--- a/source/Core/Communication.cpp
+++ b/source/Core/Communication.cpp
@@ -25,7 +25,7 @@
 //----------------------------------------------------------------------
 // Constructor
 //----------------------------------------------------------------------
-Communication::Communication(const char *name) :
+Communication::Communication(const char *name, bool close_on_eof) :
     Broadcaster (name),
     m_connection_ap (),
     m_read_thread (LLDB_INVALID_HOST_THREAD),
@@ -33,7 +33,8 @@
     m_bytes(),
     m_bytes_mutex (Mutex::eMutexTypeRecursive),
     m_callback (NULL),
-    m_callback_baton (NULL)
+    m_callback_baton (NULL),
+    m_close_on_eof (close_on_eof)
 
 {
     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
@@ -265,7 +266,8 @@
     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
                                  "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
                                  this, bytes, len, broadcast);
-    if (bytes == NULL || len == 0)
+    if ((bytes == NULL || len == 0)
+        && (status != eConnectionStatusEndOfFile))
         return;
     if (m_callback)
     {
@@ -289,6 +291,11 @@
     return 0;
 }
 
+bool
+Communication::CloseOnEOF ()
+{
+    return m_close_on_eof;
+}
 
 bool
 Communication::ReadThreadIsRunning ()
@@ -320,14 +327,21 @@
             size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error);
             if (bytes_read > 0)
                 comm->AppendBytesToCache (buf, bytes_read, true, status);
+            else if ((bytes_read == 0)
+                    && status == eConnectionStatusEndOfFile)
+            {
+                if (comm->CloseOnEOF ())
+                    comm->Disconnect ();
+                comm->AppendBytesToCache (buf, bytes_read, true, status);
+            }
         }
 
         switch (status)
         {
         case eConnectionStatusSuccess:
+        case eConnectionStatusEndOfFile:
             break;
 
-        case eConnectionStatusEndOfFile:
         case eConnectionStatusNoConnection:     // No connection
         case eConnectionStatusLostConnection:   // Lost connection while connected to a valid connection
             done = true;
diff --git a/source/Core/ConnectionFileDescriptor.cpp b/source/Core/ConnectionFileDescriptor.cpp
index 96d70bc..c333d06 100644
--- a/source/Core/ConnectionFileDescriptor.cpp
+++ b/source/Core/ConnectionFileDescriptor.cpp
@@ -156,8 +156,8 @@
     ssize_t bytes_read = ::read (m_fd, dst, dst_len);
     if (bytes_read == 0)
     {
-        error.SetErrorStringWithFormat("End-of-file.\n");
-        status = eConnectionStatusLostConnection;
+        error.Clear(); // End-of-file.  Do not automatically close; pass along for the end-of-file handlers.
+        status = eConnectionStatusEndOfFile;
     }
     else if (bytes_read < 0)
     {
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index a06095f..8884c3c 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -166,7 +166,7 @@
 Debugger::Debugger () :
     UserID (g_unique_id++),
     DebuggerInstanceSettings (*GetSettingsController()),
-    m_input_comm("debugger.input"),
+    m_input_comm("debugger.input", false),
     m_input_file (),
     m_output_file (),
     m_error_file (),
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 63fb357..be96272 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -32,7 +32,7 @@
 // GDBRemoteCommunication constructor
 //----------------------------------------------------------------------
 GDBRemoteCommunication::GDBRemoteCommunication() :
-    Communication("gdb-remote.packets"),
+    Communication("gdb-remote.packets", true),
     m_send_acks (true),
     m_rx_packet_listener ("gdbremote.rx_packet"),
     m_sequence_mutex (Mutex::eMutexTypeRecursive),
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index b025970..1c269be 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -96,7 +96,7 @@
     m_addr_byte_size (0),
     m_abi_sp (),
     m_process_input_reader (),
-    m_stdio_communication ("lldb.process.stdio"),
+    m_stdio_communication ("lldb.process.stdio", true),
     m_stdio_communication_mutex (Mutex::eMutexTypeRecursive),
     m_stdout_data ()
 {