https://github.com/charles-zablit created 
https://github.com/llvm/llvm-project/pull/207017

A closed pipe write end is EOF, not an error. On POSIX, `read()` returns 0, but 
on Windows `ReadFile` fails with `ERROR_BROKEN_PIPE`. The lldb-server 
`gdbserver/platform` pipe synchronization in 
`GDBRemoteCommunication::StartDebugserverProcess` reads the pipe until EOF, so 
without this it sees an error instead of EOF and reports the sync as failed.

Translate both broken-pipe conditions to a zero-length read so cross-platform 
callers can detect EOF uniformly.

>From 218f97a8ace4b54d3d284542ba6590478cb069d5 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Wed, 1 Jul 2026 16:54:22 +0100
Subject: [PATCH] [lldb][Windows] Return EOF from PipeWindows::Read on a closed
 write end

---
 lldb/source/Host/windows/PipeWindows.cpp | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/lldb/source/Host/windows/PipeWindows.cpp 
b/lldb/source/Host/windows/PipeWindows.cpp
index e2a64e65cee00..abf608750e61a 100644
--- a/lldb/source/Host/windows/PipeWindows.cpp
+++ b/lldb/source/Host/windows/PipeWindows.cpp
@@ -291,8 +291,15 @@ llvm::Expected<size_t> PipeWindows::Read(void *buf, size_t 
size,
     return bytes_read;
 
   DWORD failure_error = ::GetLastError();
-  if (failure_error != ERROR_IO_PENDING)
+  switch (failure_error) {
+  case ERROR_BROKEN_PIPE:
+  case ERROR_HANDLE_EOF:
+    return 0;
+  case ERROR_IO_PENDING:
+    break;
+  default:
     return Status(failure_error, eErrorTypeWin32).takeError();
+  }
 
   DWORD timeout_msec =
       timeout ? std::chrono::ceil<std::chrono::milliseconds>(*timeout).count()
@@ -319,8 +326,13 @@ llvm::Expected<size_t> PipeWindows::Read(void *buf, size_t 
size,
 
   // Now we call GetOverlappedResult setting bWait to false, since we've
   // already waited as long as we're willing to.
-  if (!::GetOverlappedResult(m_read, &m_read_overlapped, &bytes_read, FALSE))
-    return Status(::GetLastError(), eErrorTypeWin32).takeError();
+  if (!::GetOverlappedResult(m_read, &m_read_overlapped, &bytes_read, FALSE)) {
+    DWORD overlapped_error = ::GetLastError();
+    if (overlapped_error == ERROR_BROKEN_PIPE ||
+        overlapped_error == ERROR_HANDLE_EOF)
+      return 0;
+    return Status(overlapped_error, eErrorTypeWin32).takeError();
+  }
 
   return bytes_read;
 }

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to