[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

llvm-svn: 350784
diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp
index 1bf532c..866a989 100644
--- a/lldb/source/Host/posix/PipePosix.cpp
+++ b/lldb/source/Host/posix/PipePosix.cpp
@@ -61,12 +61,13 @@
 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)},
diff --git a/lldb/source/Host/windows/PipeWindows.cpp b/lldb/source/Host/windows/PipeWindows.cpp
index 1951c9c..57221a7 100644
--- a/lldb/source/Host/windows/PipeWindows.cpp
+++ b/lldb/source/Host/windows/PipeWindows.cpp
@@ -25,14 +25,41 @@
 
 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);
 
-  m_read_fd = -1;
-  m_write_fd = -1;
+  // 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;
+  }
+
   ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
   ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
 }
@@ -40,6 +67,24 @@
 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 @@
   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 @@
   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::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 @@
 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 @@
   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::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::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 @@
 
   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 @@
 
   _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));
 }
 
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index b630fae..72c1314 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -1074,9 +1074,9 @@
                         __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 {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 60df07a..3521dda 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -164,9 +164,6 @@
 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 @@
   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