Added reaper for commandline-launched processes.

GDBRemoteCommunicationServer::LaunchProcess () now uses the built-up
ProcessLaunchArgs rather than clearing and setting items from the
function arguments. I added setters for the arguments and launch
flags, which lldb-gdbserver uses for its specification of the
commandline-specified startup app (if one is specified).

LaunchProcess () also adds a new reaper monitor that it applies to
the launched process if no process monitor has already been applied.

This addresses an issue where the 'k' command would generate (possibly
false) warnings about not being able to positively state whether a
killed process actually terminated. GDBRemoteCommunicationServer now
definitely knows the disposition of its children.

llvm-svn: 199959
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 568997f..e74632f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -276,24 +276,42 @@
 }
 
 lldb_private::Error
-GDBRemoteCommunicationServer::LaunchProcess (const char *const args[], int argc, unsigned int launch_flags)
+GDBRemoteCommunicationServer::SetLaunchArguments (const char *const args[], int argc)
 {
     if ((argc < 1) || !args || !args[0] || !args[0][0])
-        lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
+        return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
 
-    // Launch the program specified in args
-    m_process_launch_info.Clear ();
     m_process_launch_info.SetArguments (const_cast<const char**> (args), true);
+    return lldb_private::Error ();
+}
+
+lldb_private::Error
+GDBRemoteCommunicationServer::SetLaunchFlags (unsigned int launch_flags)
+{
     m_process_launch_info.GetFlags ().Set (launch_flags);
+    return lldb_private::Error ();
+}
+
+lldb_private::Error
+GDBRemoteCommunicationServer::LaunchProcess ()
+{
+    if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
+        return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
+
+    // specify the process monitor if not already set.  This should
+    // generally be what happens since we need to reap started
+    // processes.
+    if (!m_process_launch_info.GetMonitorProcessCallback ())
+        m_process_launch_info.SetMonitorProcessCallback(ReapDebuggedProcess, this, false);
 
     lldb_private::Error error = Host::LaunchProcess (m_process_launch_info);
     if (!error.Success ())
     {
-        fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, args[0]);
+        fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
         return error;
     }
 
-    printf ("Launched '%s' as process %" PRIu64 "...\n", args[0], m_process_launch_info.GetProcessID());
+    printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
 
     // add to list of spawned processes.  On an lldb-gdbserver, we
     // would expect there to be only one.
@@ -846,6 +864,26 @@
     return true;
 }
 
+bool
+GDBRemoteCommunicationServer::DebuggedProcessReaped (lldb::pid_t pid)
+{
+    // reap a process that we were debugging (but not debugserver)
+    Mutex::Locker locker (m_spawned_pids_mutex);
+    return m_spawned_pids.erase(pid) > 0;
+}
+
+bool
+GDBRemoteCommunicationServer::ReapDebuggedProcess (void *callback_baton,
+                                                   lldb::pid_t pid,
+                                                   bool exited,
+                                                   int signal,    // Zero for no signal
+                                                   int status)    // Exit value of process if signal is zero
+{
+    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+    server->DebuggedProcessReaped (pid);
+    return true;
+}
+
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
 {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index c1223ad..6085016 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -139,11 +139,9 @@
     }
 
     //------------------------------------------------------------------
-    /// Launch a process.
+    /// Specify the program to launch and its arguments.
     ///
-    /// This method supports running an lldb-gdbserver or similar
-    /// server in a situation where the startup code has been provided
-    /// with all the information for a child process to be launched.
+    /// The LaunchProcess () command can be executed to do the lauching.
     ///
     /// @param[in] args
     ///     The command line to launch.
@@ -151,15 +149,41 @@
     /// @param[in] argc
     ///     The number of elements in the args array of cstring pointers.
     ///
+    /// @return
+    ///     An Error object indicating the success or failure of making
+    ///     the setting.
+    //------------------------------------------------------------------
+    lldb_private::Error
+    SetLaunchArguments (const char *const args[], int argc);
+
+    //------------------------------------------------------------------
+    /// Specify the launch flags for the process.
+    ///
+    /// The LaunchProcess () command can be executed to do the lauching.
+    ///
     /// @param[in] launch_flags
     ///     The launch flags to use when launching this process.
     ///
     /// @return
+    ///     An Error object indicating the success or failure of making
+    ///     the setting.
+    //------------------------------------------------------------------
+    lldb_private::Error
+    SetLaunchFlags (unsigned int launch_flags);
+
+    //------------------------------------------------------------------
+    /// Launch a process with the current launch settings.
+    ///
+    /// This method supports running an lldb-gdbserver or similar
+    /// server in a situation where the startup code has been provided
+    /// with all the information for a child process to be launched.
+    ///
+    /// @return
     ///     An Error object indicating the success or failure of the
     ///     launch.
     //------------------------------------------------------------------
     lldb_private::Error
-    LaunchProcess (const char *const args[], int argc, unsigned int launch_flags);
+    LaunchProcess ();
 
 protected:
     lldb::thread_t m_async_thread;
@@ -302,6 +326,16 @@
                             int status);
 
     bool
+    DebuggedProcessReaped (lldb::pid_t pid);
+
+    static bool
+    ReapDebuggedProcess (void *callback_baton,
+                         lldb::pid_t pid,
+                         bool exited,
+                         int signal,
+                         int status);
+
+    bool
     KillSpawnedProcess (lldb::pid_t pid);
 
     //------------------------------------------------------------------