Add an unnamed pipe fail-safe to launching lldb-gdbserver.

Summary:
Currently, launching lldb-gdbserver from platform on Android requires root for
mkfifo() and an explicit TMPDIR variable. This should remove both requirements.

Test Plan: Successfully launched lldb-gdbserver on a non-rooted Android device.

Reviewers: tberghammer, vharron, clayborg

Reviewed By: clayborg

Subscribers: tberghammer, lldb-commits

Differential Revision: http://reviews.llvm.org/D9307

llvm-svn: 235940
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 0470665..a6d9f95 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -770,7 +770,7 @@
         }
 
         llvm::SmallString<PATH_MAX> named_pipe_path;
-        Pipe port_named_pipe;
+        Pipe port_pipe;
 
         bool listen = false;
         if (host_and_port[0])
@@ -783,11 +783,33 @@
             {
                 // Binding to port zero, we need to figure out what port it ends up
                 // using using a named pipe...
-                error = port_named_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
-                if (error.Fail())
-                    return error;
-                debugserver_args.AppendArgument("--named-pipe");
-                debugserver_args.AppendArgument(named_pipe_path.c_str());
+                error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
+                if (error.Success())
+                {
+                    debugserver_args.AppendArgument("--named-pipe");
+                    debugserver_args.AppendArgument(named_pipe_path.c_str());
+                }
+                else
+                {
+                    if (log)
+                        log->Printf("GDBRemoteCommunication::%s() "
+                                "named pipe creation failed: %s",
+                                __FUNCTION__, error.AsCString());
+                    // let's try an unnamed pipe
+                    error = port_pipe.CreateNew(true);
+                    if (error.Fail())
+                    {
+                        if (log)
+                            log->Printf("GDBRemoteCommunication::%s() "
+                                    "unnamed pipe creation failed: %s",
+                                    __FUNCTION__, error.AsCString());
+                        return error;
+                    }
+                    int write_fd = port_pipe.GetWriteFileDescriptor();
+                    debugserver_args.AppendArgument("--pipe");
+                    debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
+                    launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor());
+                }
             }
             else
             {
@@ -869,50 +891,57 @@
         {
             if (named_pipe_path.size() > 0)
             {
-                error = port_named_pipe.OpenAsReader(named_pipe_path, false);
+                error = port_pipe.OpenAsReader(named_pipe_path, false);
+                if (error.Fail())
+                    if (log)
+                        log->Printf("GDBRemoteCommunication::%s() "
+                                "failed to open named pipe %s for reading: %s",
+                                __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
+            }
+
+            if (port_pipe.CanWrite())
+                port_pipe.CloseWriteFileDescriptor();
+            if (port_pipe.CanRead())
+            {
+                char port_cstr[256];
+                port_cstr[0] = '\0';
+                size_t num_bytes = sizeof(port_cstr);
+                // Read port from pipe with 10 second timeout.
+                error = port_pipe.ReadWithTimeout(port_cstr, num_bytes,
+                        std::chrono::seconds{10}, num_bytes);
                 if (error.Success())
                 {
-                    char port_cstr[256];
-                    port_cstr[0] = '\0';
-                    size_t num_bytes = sizeof(port_cstr);
-                    // Read port from pipe with 10 second timeout.
-                    error = port_named_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::microseconds(10 * 1000000), num_bytes);
-                    if (error.Success())
-                    {
-                        assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
-                        out_port = StringConvert::ToUInt32(port_cstr, 0);
-                        if (log)
-                            log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port);
-                    }
-                    else
-                    {
-                        if (log)
-                            log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
-
-                    }
-                    port_named_pipe.Close();
+                    assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
+                    out_port = StringConvert::ToUInt32(port_cstr, 0);
+                    if (log)
+                        log->Printf("GDBRemoteCommunication::%s() "
+                                "debugserver listens %u port",
+                                __FUNCTION__, out_port);
                 }
                 else
                 {
                     if (log)
-                        log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
+                        log->Printf("GDBRemoteCommunication::%s() "
+                                "failed to read a port value from pipe %s: %s",
+                                __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
+
                 }
-                const auto err = port_named_pipe.Delete(named_pipe_path);
+                port_pipe.Close();
+            }
+
+            if (named_pipe_path.size() > 0)
+            {
+                const auto err = port_pipe.Delete(named_pipe_path);
                 if (err.Fail())
                 {
                     if (log)
-                        log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), err.AsCString());
+                        log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s",
+                                __FUNCTION__, named_pipe_path.c_str(), err.AsCString());
                 }
             }
-            else if (listen)
-            {
-                
-            }
-            else
-            {
-                // Make sure we actually connect with the debugserver...
-                JoinListenThread();
-            }
+
+            // Make sure we actually connect with the debugserver...
+            JoinListenThread();
         }
     }
     else