[Lldb-commits] [lldb] d6e1e01 - [lldb] [Core] Harmonize Communication::Read() returns w/ thread

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Fri Aug 19 06:36:14 PDT 2022


Author: Michał Górny
Date: 2022-08-19T15:36:03+02:00
New Revision: d6e1e01da949c8cb4b869cee1953cf19a6d072c0

URL: https://github.com/llvm/llvm-project/commit/d6e1e01da949c8cb4b869cee1953cf19a6d072c0
DIFF: https://github.com/llvm/llvm-project/commit/d6e1e01da949c8cb4b869cee1953cf19a6d072c0.diff

LOG: [lldb] [Core] Harmonize Communication::Read() returns w/ thread

Harmonize the status and error values of Communication::Read() when
running with and without read thread.  Prior to this change, Read()
would return eConnectionStatusSuccess if read thread was enabled
and the read timed out or reached end-of-file, rather than
the respective states that are returned if read thread was disabled.
Now, it correctly returns eConnectionStatusTimedOut
and eConnectionStatusEndOfFile, and sets the error respectively.

Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.llvm.org/D132217

Added: 
    

Modified: 
    lldb/source/Core/Communication.cpp
    lldb/unittests/Core/CommunicationTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp
index d5f8f8922f5e1..56f0990d8c7f7 100644
--- a/lldb/source/Core/Communication.cpp
+++ b/lldb/source/Core/Communication.cpp
@@ -132,10 +132,16 @@ size_t Communication::Read(void *dst, size_t dst_len,
   if (m_read_thread_enabled) {
     // We have a dedicated read thread that is getting data for us
     size_t cached_bytes = GetCachedBytes(dst, dst_len);
-    if (cached_bytes > 0 || (timeout && timeout->count() == 0)) {
+    if (cached_bytes > 0) {
       status = eConnectionStatusSuccess;
       return cached_bytes;
     }
+    if (timeout && timeout->count() == 0) {
+      if (error_ptr)
+        error_ptr->SetErrorString("Timed out.");
+      status = eConnectionStatusTimedOut;
+      return 0;
+    }
 
     if (!m_connection_sp) {
       if (error_ptr)
@@ -155,11 +161,25 @@ size_t Communication::Read(void *dst, size_t dst_len,
       }
 
       if (event_type & eBroadcastBitReadThreadDidExit) {
+        // If the thread exited of its own accord, it either means it
+        // hit an end-of-file condition or lost connection
+        // (we verified that we had an connection above).
+        if (!m_connection_sp) {
+          if (error_ptr)
+            error_ptr->SetErrorString("Lost connection.");
+          status = eConnectionStatusLostConnection;
+        } else
+          status = eConnectionStatusEndOfFile;
+
         if (GetCloseOnEOF())
           Disconnect(nullptr);
-        break;
+        return 0;
       }
     }
+
+    if (error_ptr)
+      error_ptr->SetErrorString("Timed out.");
+    status = eConnectionStatusTimedOut;
     return 0;
   }
 

diff  --git a/lldb/unittests/Core/CommunicationTest.cpp b/lldb/unittests/Core/CommunicationTest.cpp
index bb57a7b14670f..024684a486c2d 100644
--- a/lldb/unittests/Core/CommunicationTest.cpp
+++ b/lldb/unittests/Core/CommunicationTest.cpp
@@ -21,6 +21,72 @@
 
 using namespace lldb_private;
 
+static void CommunicationReadTest(bool use_read_thread) {
+  Pipe pipe;
+  ASSERT_THAT_ERROR(pipe.CreateNew(/*child_process_inherit=*/false).ToError(),
+                    llvm::Succeeded());
+
+  Status error;
+  size_t bytes_written;
+  ASSERT_THAT_ERROR(pipe.Write("test", 4, bytes_written).ToError(),
+                    llvm::Succeeded());
+  ASSERT_EQ(bytes_written, 4U);
+
+  Communication comm("test");
+  comm.SetConnection(std::make_unique<ConnectionFileDescriptor>(
+      pipe.ReleaseReadFileDescriptor(), /*owns_fd=*/true));
+  comm.SetCloseOnEOF(true);
+
+  if (use_read_thread)
+    ASSERT_TRUE(comm.StartReadThread());
+
+  // This read should wait for the data to become available and return it.
+  lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
+  char buf[16];
+  error.Clear();
+  EXPECT_EQ(
+      comm.Read(buf, sizeof(buf), std::chrono::seconds(5), status, &error), 4U);
+  EXPECT_EQ(status, lldb::eConnectionStatusSuccess);
+  EXPECT_THAT_ERROR(error.ToError(), llvm::Succeeded());
+  buf[4] = 0;
+  EXPECT_STREQ(buf, "test");
+
+  // These reads should time out as there is no more data.
+  error.Clear();
+  EXPECT_EQ(comm.Read(buf, sizeof(buf), std::chrono::microseconds(10), status,
+                      &error),
+            0U);
+  EXPECT_EQ(status, lldb::eConnectionStatusTimedOut);
+  EXPECT_THAT_ERROR(error.ToError(), llvm::Failed());
+
+  // 0 is special-cased, so we test it separately.
+  error.Clear();
+  EXPECT_EQ(
+      comm.Read(buf, sizeof(buf), std::chrono::seconds(0), status, &error), 0U);
+  EXPECT_EQ(status, lldb::eConnectionStatusTimedOut);
+  EXPECT_THAT_ERROR(error.ToError(), llvm::Failed());
+
+  // This read should return EOF.
+  pipe.CloseWriteFileDescriptor();
+  error.Clear();
+  EXPECT_EQ(
+      comm.Read(buf, sizeof(buf), std::chrono::seconds(5), status, &error), 0U);
+  EXPECT_EQ(status, lldb::eConnectionStatusEndOfFile);
+  EXPECT_THAT_ERROR(error.ToError(), llvm::Succeeded());
+
+  // JoinReadThread() should just return immediately since there was no read
+  // thread started.
+  EXPECT_TRUE(comm.JoinReadThread());
+}
+
+TEST(CommunicationTest, Read) {
+  CommunicationReadTest(/*use_thread=*/false);
+}
+
+TEST(CommunicationTest, ReadThread) {
+  CommunicationReadTest(/*use_thread=*/true);
+}
+
 #ifndef _WIN32
 TEST(CommunicationTest, SynchronizeWhileClosing) {
   // Set up a communication object reading from a pipe.


        


More information about the lldb-commits mailing list