Switch local launching of debugserver over to always use a FIFO in order to handshake with the launched debugserver.

This helps ensure that the launched debugserver is ready and listening for a connection. Prior to this we had a race condition.

Consolidate the launching of debugserver into a single place: a static function in GDBRemoteCommunication.

llvm-svn: 196401
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index f67e1b5..d53347a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -13,6 +13,7 @@
 // C Includes
 #include <limits.h>
 #include <string.h>
+#include <sys/stat.h>
 
 // C++ Includes
 // Other libraries and framework includes
@@ -539,9 +540,11 @@
 
 Error
 GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
-                                                 const char *unix_socket_name,  // For handshaking
-                                                 lldb_private::ProcessLaunchInfo &launch_info)
+                                                 lldb_private::ProcessLaunchInfo &launch_info,
+                                                 uint16_t &port)
 {
+    port = 0;
+
     Error error;
     // If we locate debugserver, keep that located version around
     static FileSpec g_debugserver_file_spec;
@@ -598,11 +601,34 @@
         // special terminal key sequences (^C) don't affect debugserver
         debugserver_args.AppendArgument("--setsid");
         
-        if (unix_socket_name && unix_socket_name[0])
+        char named_pipe_path[PATH_MAX];
+        
+        // Create a temporary file to get the stdout/stderr and redirect the
+        // output of the command into this file. We will later read this file
+        // if all goes well and fill the data into "command_output_ptr"
+        FileSpec tmpdir_file_spec;
+        if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
         {
-            debugserver_args.AppendArgument("--unix-socket");
-            debugserver_args.AppendArgument(unix_socket_name);
+            tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
+            strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
         }
+        else
+        {
+            strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
+        }
+
+        if (::mktemp (named_pipe_path))
+        {
+            if (::mkfifo(named_pipe_path, 0600) == 0)
+            {
+                debugserver_args.AppendArgument("--named-pipe");
+                debugserver_args.AppendArgument(named_pipe_path);
+            }
+            else
+                named_pipe_path[0] = '\0';
+        }
+        else
+            named_pipe_path[0] = '\0';
 
         const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
         if (env_debugserver_log_file)
@@ -617,46 +643,33 @@
             ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
             debugserver_args.AppendArgument(arg_cstr);
         }
-        //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
-        //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
-        
-        // We currently send down all arguments, attach pids, or attach 
-        // process names in dedicated GDB server packets, so we don't need
-        // to pass them as arguments. This is currently because of all the
-        // things we need to setup prior to launching: the environment,
-        // current working dir, file actions, etc.
-#if 0
-        // Now append the program arguments
-        if (inferior_argv)
-        {
-            // Terminate the debugserver args so we can now append the inferior args
-            debugserver_args.AppendArgument("--");
-            
-            for (int i = 0; inferior_argv[i] != NULL; ++i)
-                debugserver_args.AppendArgument (inferior_argv[i]);
-        }
-        else if (attach_pid != LLDB_INVALID_PROCESS_ID)
-        {
-            ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
-            debugserver_args.AppendArgument (arg_cstr);
-        }
-        else if (attach_name && attach_name[0])
-        {
-            if (wait_for_launch)
-                debugserver_args.AppendArgument ("--waitfor");
-            else
-                debugserver_args.AppendArgument ("--attach");
-            debugserver_args.AppendArgument (attach_name);
-        }
-#endif
         
         // Close STDIN, STDOUT and STDERR. We might need to redirect them
         // to "/dev/null" if we run into any problems.
-//        launch_info.AppendCloseFileAction (STDIN_FILENO);
-//        launch_info.AppendCloseFileAction (STDOUT_FILENO);
-//        launch_info.AppendCloseFileAction (STDERR_FILENO);
+        launch_info.AppendCloseFileAction (STDIN_FILENO);
+        launch_info.AppendCloseFileAction (STDOUT_FILENO);
+        launch_info.AppendCloseFileAction (STDERR_FILENO);
         
         error = Host::LaunchProcess(launch_info);
+        
+        if (named_pipe_path[0])
+        {
+            File name_pipe_file;
+            error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
+            if (error.Success())
+            {
+                char port_cstr[256];
+                port_cstr[0] = '\0';
+                size_t num_bytes = sizeof(port_cstr);
+                error = name_pipe_file.Read(port_cstr, num_bytes);
+                assert (error.Success());
+                assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
+                port = Args::StringToUInt32(port_cstr, 0);
+                name_pipe_file.Close();
+            }
+            Host::Unlink(named_pipe_path);
+        }
+
     }
     else
     {