[Lldb-commits] [lldb] r350784 - [lldb-server] Add unnamed pipe support to PipeWindows

Aaron Smith via lldb-commits lldb-commits at lists.llvm.org
Wed Jan 9 16:46:10 PST 2019


Author: asmith
Date: Wed Jan  9 16:46:09 2019
New Revision: 350784

URL: http://llvm.org/viewvc/llvm-project?rev=350784&view=rev
Log:
[lldb-server] Add unnamed pipe support to PipeWindows

Summary:
This adds unnamed pipe support in PipeWindows to support communication between a debug server and child process.
Modify PipeWindows::CreateNew to support the creation of an unnamed pipe.
Rename the previous method that created a named pipe to PipeWindows::CreateNewNamed.

Reviewers: zturner, llvm-commits

Reviewed By: zturner

Subscribers: Hui, labath, lldb-commits

Differential Revision: https://reviews.llvm.org/D56234

Modified:
    lldb/trunk/include/lldb/Host/PipeBase.h
    lldb/trunk/include/lldb/Host/posix/PipePosix.h
    lldb/trunk/include/lldb/Host/windows/PipeWindows.h
    lldb/trunk/include/lldb/lldb-types.h
    lldb/trunk/source/Host/posix/PipePosix.cpp
    lldb/trunk/source/Host/windows/PipeWindows.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
    lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp

Modified: lldb/trunk/include/lldb/Host/PipeBase.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/PipeBase.h?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/PipeBase.h (original)
+++ lldb/trunk/include/lldb/Host/PipeBase.h Wed Jan  9 16:46:09 2019
@@ -41,6 +41,9 @@ public:
   virtual bool CanRead() const = 0;
   virtual bool CanWrite() const = 0;
 
+  virtual lldb::pipe_t GetReadPipe() const = 0;
+  virtual lldb::pipe_t GetWritePipe() const = 0;
+
   virtual int GetReadFileDescriptor() const = 0;
   virtual int GetWriteFileDescriptor() const = 0;
   virtual int ReleaseReadFileDescriptor() = 0;

Modified: lldb/trunk/include/lldb/Host/posix/PipePosix.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/posix/PipePosix.h?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/posix/PipePosix.h (original)
+++ lldb/trunk/include/lldb/Host/posix/PipePosix.h Wed Jan  9 16:46:09 2019
@@ -27,7 +27,7 @@ public:
   static int kInvalidDescriptor;
 
   PipePosix();
-  PipePosix(int read_fd, int write_fd);
+  PipePosix(lldb::pipe_t read, lldb::pipe_t write);
   PipePosix(const PipePosix &) = delete;
   PipePosix(PipePosix &&pipe_posix);
   PipePosix &operator=(const PipePosix &) = delete;
@@ -49,6 +49,13 @@ public:
   bool CanRead() const override;
   bool CanWrite() const override;
 
+  lldb::pipe_t GetReadPipe() const override {
+    return lldb::pipe_t(GetReadFileDescriptor());
+  }
+  lldb::pipe_t GetWritePipe() const override {
+    return lldb::pipe_t(GetWriteFileDescriptor());
+  }
+
   int GetReadFileDescriptor() const override;
   int GetWriteFileDescriptor() const override;
   int ReleaseReadFileDescriptor() override;

Modified: lldb/trunk/include/lldb/Host/windows/PipeWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/windows/PipeWindows.h?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/windows/PipeWindows.h (original)
+++ lldb/trunk/include/lldb/Host/windows/PipeWindows.h Wed Jan  9 16:46:09 2019
@@ -24,10 +24,18 @@ namespace lldb_private {
 //----------------------------------------------------------------------
 class PipeWindows : public PipeBase {
 public:
+  static const int kInvalidDescriptor = -1;
+
+public:
   PipeWindows();
+  PipeWindows(lldb::pipe_t read, lldb::pipe_t write);
   ~PipeWindows() override;
 
+  // Create an unnamed pipe.
   Status CreateNew(bool child_process_inherit) override;
+
+  // Create a named pipe.
+  Status CreateNewNamed(bool child_process_inherit);
   Status CreateNew(llvm::StringRef name, bool child_process_inherit) override;
   Status CreateWithUniqueName(llvm::StringRef prefix,
                               bool child_process_inherit,
@@ -41,6 +49,9 @@ public:
   bool CanRead() const override;
   bool CanWrite() const override;
 
+  lldb::pipe_t GetReadPipe() const { return lldb::pipe_t(m_read); }
+  lldb::pipe_t GetWritePipe() const { return lldb::pipe_t(m_write); }
+
   int GetReadFileDescriptor() const override;
   int GetWriteFileDescriptor() const override;
   int ReleaseReadFileDescriptor() override;

Modified: lldb/trunk/include/lldb/lldb-types.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-types.h?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-types.h (original)
+++ lldb/trunk/include/lldb/lldb-types.h Wed Jan  9 16:46:09 2019
@@ -47,7 +47,8 @@ typedef unsigned int __w64 socket_t; //
 typedef void *thread_arg_t;                       // Host thread argument type
 typedef unsigned thread_result_t;                 // Host thread result type
 typedef thread_result_t (*thread_func_t)(void *); // Host thread function type
-}
+typedef void *pipe_t;                             // Host pipe type is HANDLE
+} // namespace lldb
 
 #else
 
@@ -65,6 +66,7 @@ typedef int socket_t;       // Host sock
 typedef void *thread_arg_t;             // Host thread argument type
 typedef void *thread_result_t;          // Host thread result type
 typedef void *(*thread_func_t)(void *); // Host thread function type
+typedef int pipe_t;                     // Host pipe type
 } // namespace lldb
 
 #endif
@@ -76,10 +78,11 @@ typedef bool (*CommandOverrideCallbackWi
     void *baton, const char **argv, lldb_private::CommandReturnObject &result);
 typedef bool (*ExpressionCancelCallback)(ExpressionEvaluationPhase phase,
                                          void *baton);
-}
+} // namespace lldb
 
 #define LLDB_INVALID_PROCESS ((lldb::process_t)-1)
 #define LLDB_INVALID_HOST_THREAD ((lldb::thread_t)NULL)
+#define LLDB_INVALID_PIPE ((lldb::pipe_t)-1)
 
 namespace lldb {
 typedef uint64_t addr_t;
@@ -91,6 +94,6 @@ typedef int32_t break_id_t;
 typedef int32_t watch_id_t;
 typedef void *opaque_compiler_type_t;
 typedef uint64_t queue_id_t;
-}
+} // namespace lldb
 
 #endif // LLDB_lldb_types_h_

Modified: lldb/trunk/source/Host/posix/PipePosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/PipePosix.cpp?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/PipePosix.cpp (original)
+++ lldb/trunk/source/Host/posix/PipePosix.cpp Wed Jan  9 16:46:09 2019
@@ -61,12 +61,13 @@ bool SetCloexecFlag(int fd) {
 std::chrono::time_point<std::chrono::steady_clock> Now() {
   return std::chrono::steady_clock::now();
 }
-}
+} // namespace
 
 PipePosix::PipePosix()
     : m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {}
 
-PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {}
+PipePosix::PipePosix(lldb::pipe_t read, lldb::pipe_t write)
+    : m_fds{read, write} {}
 
 PipePosix::PipePosix(PipePosix &&pipe_posix)
     : PipeBase{std::move(pipe_posix)},

Modified: lldb/trunk/source/Host/windows/PipeWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/PipeWindows.cpp?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/PipeWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/PipeWindows.cpp Wed Jan  9 16:46:09 2019
@@ -25,14 +25,41 @@ using namespace lldb_private;
 
 namespace {
 std::atomic<uint32_t> g_pipe_serial(0);
+constexpr llvm::StringLiteral g_pipe_name_prefix = "\\\\.\\Pipe\\";
+} // namespace
+
+PipeWindows::PipeWindows()
+    : m_read(INVALID_HANDLE_VALUE), m_write(INVALID_HANDLE_VALUE),
+      m_read_fd(PipeWindows::kInvalidDescriptor),
+      m_write_fd(PipeWindows::kInvalidDescriptor) {
+  ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+  ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
 }
 
-PipeWindows::PipeWindows() {
-  m_read = INVALID_HANDLE_VALUE;
-  m_write = INVALID_HANDLE_VALUE;
+PipeWindows::PipeWindows(pipe_t read, pipe_t write)
+    : m_read((HANDLE)read), m_write((HANDLE)write),
+      m_read_fd(PipeWindows::kInvalidDescriptor),
+      m_write_fd(PipeWindows::kInvalidDescriptor) {
+  assert(read != LLDB_INVALID_PIPE || write != LLDB_INVALID_PIPE);
+
+  // Don't risk in passing file descriptors and getting handles from them by
+  // _get_osfhandle since the retrieved handles are highly likely unrecognized
+  // in the current process and usually crashes the program.  Pass handles
+  // instead since the handle can be inherited.
+
+  if (read != LLDB_INVALID_PIPE) {
+    m_read_fd = _open_osfhandle((intptr_t)read, _O_RDONLY);
+    // Make sure the fd and native handle are consistent.
+    if (m_read_fd < 0)
+      m_read = INVALID_HANDLE_VALUE;
+  }
+
+  if (write != LLDB_INVALID_PIPE) {
+    m_write_fd = _open_osfhandle((intptr_t)write, _O_WRONLY);
+    if (m_write_fd < 0)
+      m_write = INVALID_HANDLE_VALUE;
+  }
 
-  m_read_fd = -1;
-  m_write_fd = -1;
   ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
   ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
 }
@@ -40,6 +67,24 @@ PipeWindows::PipeWindows() {
 PipeWindows::~PipeWindows() { Close(); }
 
 Status PipeWindows::CreateNew(bool child_process_inherit) {
+  // Create an anonymous pipe with the specified inheritance.
+  SECURITY_ATTRIBUTES sa{sizeof(SECURITY_ATTRIBUTES), 0,
+                         child_process_inherit ? TRUE : FALSE};
+  BOOL result = ::CreatePipe(&m_read, &m_write, &sa, 1024);
+  if (result == FALSE)
+    return Status(::GetLastError(), eErrorTypeWin32);
+
+  m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
+  ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+  m_read_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
+
+  m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
+  ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+
+  return Status();
+}
+
+Status PipeWindows::CreateNewNamed(bool child_process_inherit) {
   // Even for anonymous pipes, we open a named pipe.  This is because you
   // cannot get overlapped i/o on Windows without using a named pipe.  So we
   // synthesize a unique name.
@@ -60,7 +105,7 @@ Status PipeWindows::CreateNew(llvm::Stri
   if (CanRead() || CanWrite())
     return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
 
-  std::string pipe_path = "\\\\.\\Pipe\\";
+  std::string pipe_path = g_pipe_name_prefix;
   pipe_path.append(name);
 
   // Always open for overlapped i/o.  We implement blocking manually in Read
@@ -75,7 +120,8 @@ Status PipeWindows::CreateNew(llvm::Stri
   ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
   m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
 
-  // Open the write end of the pipe.
+  // Open the write end of the pipe. Note that closing either the read or 
+  // write end of the pipe could directly close the pipe itself.
   Status result = OpenNamedPipe(name, child_process_inherit, false);
   if (!result.Success()) {
     CloseReadFileDescriptor();
@@ -111,7 +157,7 @@ Status PipeWindows::CreateWithUniqueName
 
 Status PipeWindows::OpenAsReader(llvm::StringRef name,
                                  bool child_process_inherit) {
-  if (CanRead() || CanWrite())
+  if (CanRead())
     return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
 
   return OpenNamedPipe(name, child_process_inherit, true);
@@ -121,7 +167,7 @@ Status
 PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name,
                                      bool child_process_inherit,
                                      const std::chrono::microseconds &timeout) {
-  if (CanRead() || CanWrite())
+  if (CanWrite())
     return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
 
   return OpenNamedPipe(name, child_process_inherit, false);
@@ -137,7 +183,7 @@ Status PipeWindows::OpenNamedPipe(llvm::
   SECURITY_ATTRIBUTES attributes = {};
   attributes.bInheritHandle = child_process_inherit;
 
-  std::string pipe_path = "\\\\.\\Pipe\\";
+  std::string pipe_path = g_pipe_name_prefix;
   pipe_path.append(name);
 
   if (is_read) {
@@ -170,9 +216,9 @@ int PipeWindows::GetWriteFileDescriptor(
 
 int PipeWindows::ReleaseReadFileDescriptor() {
   if (!CanRead())
-    return -1;
+    return PipeWindows::kInvalidDescriptor;
   int result = m_read_fd;
-  m_read_fd = -1;
+  m_read_fd = PipeWindows::kInvalidDescriptor;
   if (m_read_overlapped.hEvent)
     ::CloseHandle(m_read_overlapped.hEvent);
   m_read = INVALID_HANDLE_VALUE;
@@ -182,9 +228,9 @@ int PipeWindows::ReleaseReadFileDescript
 
 int PipeWindows::ReleaseWriteFileDescriptor() {
   if (!CanWrite())
-    return -1;
+    return PipeWindows::kInvalidDescriptor;
   int result = m_write_fd;
-  m_write_fd = -1;
+  m_write_fd = PipeWindows::kInvalidDescriptor;
   m_write = INVALID_HANDLE_VALUE;
   ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
   return result;
@@ -196,9 +242,10 @@ void PipeWindows::CloseReadFileDescripto
 
   if (m_read_overlapped.hEvent)
     ::CloseHandle(m_read_overlapped.hEvent);
+
   _close(m_read_fd);
   m_read = INVALID_HANDLE_VALUE;
-  m_read_fd = -1;
+  m_read_fd = PipeWindows::kInvalidDescriptor;
   ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
 }
 
@@ -208,7 +255,7 @@ void PipeWindows::CloseWriteFileDescript
 
   _close(m_write_fd);
   m_write = INVALID_HANDLE_VALUE;
-  m_write_fd = -1;
+  m_write_fd = PipeWindows::kInvalidDescriptor;
   ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
 }
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Wed Jan  9 16:46:09 2019
@@ -1074,9 +1074,9 @@ Status GDBRemoteCommunication::StartDebu
                         __FUNCTION__, error.AsCString());
           return error;
         }
-        int write_fd = socket_pipe.GetWriteFileDescriptor();
+        pipe_t write = socket_pipe.GetWritePipe();
         debugserver_args.AppendArgument(llvm::StringRef("--pipe"));
-        debugserver_args.AppendArgument(llvm::to_string(write_fd));
+        debugserver_args.AppendArgument(llvm::to_string(write));
         launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
 #endif
       } else {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp Wed Jan  9 16:46:09 2019
@@ -164,9 +164,6 @@ Status GDBRemoteCommunicationServerPlatf
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
     StringExtractorGDBRemote &packet) {
-#ifdef _WIN32
-  return SendErrorResponse(9);
-#else
   // Spawn a local debugserver as a platform so we can then attach or launch a
   // process...
 
@@ -217,10 +214,9 @@ GDBRemoteCommunicationServerPlatform::Ha
   PacketResult packet_result = SendPacketNoLock(response.GetString());
   if (packet_result != PacketResult::Success) {
     if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
-      ::kill(debugserver_pid, SIGINT);
+      Host::Kill(debugserver_pid, SIGINT);
   }
   return packet_result;
-#endif
 }
 
 GDBRemoteCommunication::PacketResult

Modified: lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp?rev=350784&r1=350783&r2=350784&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp (original)
+++ lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp Wed Jan  9 16:46:09 2019
@@ -218,20 +218,17 @@ Status writeSocketIdToPipe(const char *c
   return writeSocketIdToPipe(port_name_pipe, socket_id);
 }
 
-Status writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) {
-#if defined(_WIN32)
-  return Status("Unnamed pipes are not supported on Windows.");
-#else
-  Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd};
+Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,
+                           const std::string &socket_id) {
+  Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe};
   return writeSocketIdToPipe(port_pipe, socket_id);
-#endif
 }
 
 void ConnectToRemote(MainLoop &mainloop,
                      GDBRemoteCommunicationServerLLGS &gdb_server,
                      bool reverse_connect, const char *const host_and_port,
                      const char *const progname, const char *const subcommand,
-                     const char *const named_pipe_path, int unnamed_pipe_fd,
+                     const char *const named_pipe_path, pipe_t unnamed_pipe,
                      int connection_fd) {
   Status error;
 
@@ -331,8 +328,8 @@ void ConnectToRemote(MainLoop &mainloop,
         }
         // If we have an unnamed pipe to write the socket id back to, do that
         // now.
-        else if (unnamed_pipe_fd >= 0) {
-          error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id);
+        else if (unnamed_pipe != LLDB_INVALID_PIPE) {
+          error = writeSocketIdToPipe(unnamed_pipe, socket_id);
           if (error.Fail())
             fprintf(stderr, "failed to write to the unnamed pipe: %s\n",
                     error.AsCString());
@@ -384,7 +381,7 @@ int main_gdbserver(int argc, char *argv[
   std::string log_file;
   StringRef
       log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
-  int unnamed_pipe_fd = -1;
+  lldb::pipe_t unnamed_pipe = LLDB_INVALID_PIPE;
   bool reverse_connect = false;
   int connection_fd = -1;
 
@@ -425,7 +422,7 @@ int main_gdbserver(int argc, char *argv[
 
     case 'U': // unnamed pipe
       if (optarg && optarg[0])
-        unnamed_pipe_fd = StringConvert::ToUInt32(optarg, -1);
+        unnamed_pipe = (pipe_t)StringConvert::ToUInt64(optarg, -1);
       break;
 
     case 'r':
@@ -528,8 +525,8 @@ int main_gdbserver(int argc, char *argv[
   printf("%s-%s", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
 
   ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port,
-                  progname, subcommand, named_pipe_path.c_str(),
-                  unnamed_pipe_fd, connection_fd);
+                  progname, subcommand, named_pipe_path.c_str(), 
+                  unnamed_pipe, connection_fd);
 
   if (!gdb_server.IsConnected()) {
     fprintf(stderr, "no connection information provided, unable to run\n");




More information about the lldb-commits mailing list