[Lldb-commits] [lldb] 9a95dd1 - [lldb] Let the host platform write to pipes

via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 15 07:58:23 PDT 2026


Author: Andrew Gontarek
Date: 2026-10-15T14:58:15Z
New Revision: 9a95dd1e4323bc4c439c2e9eb1128d089b63a29f

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

LOG: [lldb] Let the host platform write to pipes

`Platform::WriteFile` on the host platform could not write to a pipe: it
goes to `FileCache::WriteFile`, which seeks to the offset before
writing, and a pipe refuses the seek with ESPIPE. The offset means
nothing for a pipe, so `FileCache::WriteFile` now writes at the pipe's
end when the seek fails that way.

This is the host-side counterpart of #232045, which does the same for
lldb-server's `vFile:pwrite`. With both, writing to a pipe through a
platform works the same whether the platform is the host or a remote
one. Downstream, NVIDIA's GPU support writes a byte to a pipe in the
debugged process through the target's platform, to ask the CUDA driver
to attach.

The new FileCacheTest opens a named pipe through `FileCache`, writes to
it at a nonzero offset, and reads back exactly the bytes sent. Without
the fix, the write fails with ESPIPE. The test is POSIX-only, since
named pipes are files only there.

Added: 
    lldb/unittests/Host/FileCacheTest.cpp

Modified: 
    lldb/source/Host/common/FileCache.cpp
    lldb/unittests/Host/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/source/Host/common/FileCache.cpp b/lldb/source/Host/common/FileCache.cpp
index b8aaa0f88f1efa..40275f0b34981e 100644
--- a/lldb/source/Host/common/FileCache.cpp
+++ b/lldb/source/Host/common/FileCache.cpp
@@ -11,6 +11,8 @@
 #include "lldb/Host/File.h"
 #include "lldb/Host/FileSystem.h"
 
+#include <cerrno>
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -80,8 +82,13 @@ uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset,
     return UINT64_MAX;
   }
   if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
-      error.Fail())
-    return UINT64_MAX;
+      error.Fail()) {
+    // A pipe cannot seek, so the seek fails on it with ESPIPE. The offset
+    // means nothing there, so write at the pipe's end instead.
+    if (error.GetError() != ESPIPE)
+      return UINT64_MAX;
+    error.Clear();
+  }
   size_t bytes_written = src_len;
   error = file_up->Write(src, bytes_written);
   if (error.Fail())

diff  --git a/lldb/unittests/Host/CMakeLists.txt b/lldb/unittests/Host/CMakeLists.txt
index 285f93de58c60e..7ecc9c76f6d399 100644
--- a/lldb/unittests/Host/CMakeLists.txt
+++ b/lldb/unittests/Host/CMakeLists.txt
@@ -1,6 +1,7 @@
 set (FILES
   ConnectionFileDescriptorTest.cpp
   FileActionTest.cpp
+  FileCacheTest.cpp
   FileSystemTest.cpp
   FileTest.cpp
   HostInfoTest.cpp

diff  --git a/lldb/unittests/Host/FileCacheTest.cpp b/lldb/unittests/Host/FileCacheTest.cpp
new file mode 100644
index 00000000000000..e7a5942cc7fa5f
--- /dev/null
+++ b/lldb/unittests/Host/FileCacheTest.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/FileCache.h"
+#include "TestingSupport/SubsystemRAII.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Pipe.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+class FileCacheTest : public testing::Test {
+public:
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
+};
+
+// Named pipes are files only on POSIX.
+#ifndef _WIN32
+TEST_F(FileCacheTest, WriteToPipe) {
+  Pipe pipe;
+  llvm::SmallString<0> name;
+  ASSERT_THAT_ERROR(
+      pipe.CreateWithUniqueName("FileCacheTest-WriteToPipe", name).ToError(),
+      llvm::Succeeded());
+  llvm::scope_exit delete_pipe([&] { pipe.Delete(name); });
+  // With the read end open, opening the write end does not block.
+  ASSERT_THAT_ERROR(pipe.OpenAsReader(name).ToError(), llvm::Succeeded());
+
+  FileCache &cache = FileCache::GetInstance();
+  Status error;
+  lldb::user_id_t fd =
+      cache.OpenFile(FileSpec(name), File::eOpenOptionWriteOnly, 0, error);
+  ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
+  // A pipe cannot seek, so the bytes go to its end whatever the offset.
+  EXPECT_EQ(cache.WriteFile(fd, /*offset=*/1, "abc", 3, error), 3u);
+  EXPECT_THAT_ERROR(error.ToError(), llvm::Succeeded());
+  EXPECT_TRUE(cache.CloseFile(fd, error));
+
+  char buffer[3];
+  ASSERT_THAT_EXPECTED(pipe.Read(buffer, sizeof(buffer)), llvm::HasValue(3));
+  EXPECT_EQ(llvm::StringRef(buffer, sizeof(buffer)), "abc");
+}
+#endif


        


More information about the lldb-commits mailing list