Hi clayborg, jingham,

This implements Host::LaunchProcess for windows, and in doing so does some 
minor refactor to move towards a more modular process launching design, as 
discussed in detail previously on the list.

The original motivation for this is that launching processes on windows needs 
some very windows specific code, which would live most appropriately in 
source/Host/windows somewhere.  However, there is already some common code that 
all platforms use when launching a process before delegating to the platform 
specific stuff, which lives in source/Host/common/Host.cpp which would be nice 
to reuse without duplicating.  

This commonality has been abstracted into MonitoringProcessLauncher, a class 
which abstracts out the notion of launching a process using an arbitrary 
algorithm, and then monitoring it for state changes.  

The windows specific launching code lives in ProcessLauncherWindows, and the 
posix specific launching code lives in ProcessLauncherPosix.  after the 
refactor, a MonitoringProcessLauncher is created, and then an appropriate 
delegate launcher is created and given to the MonitoringProcessLauncher.

Comments have been inserted to indicate future places for cleanup, so that this 
refactor can happen iteratively instead as one massive risky CL.

Tested on Windows, MacOSX, and Linux.  Did not see any test regressions.

http://reviews.llvm.org/D5781

Files:
  include/lldb/Host/Host.h
  include/lldb/Host/HostNativeProcessBase.h
  include/lldb/Host/HostProcess.h
  include/lldb/Host/MonitoringProcessLauncher.h
  include/lldb/Host/ProcessLauncher.h
  include/lldb/Host/posix/HostProcessPosix.h
  include/lldb/Host/posix/ProcessLauncherPosix.h
  include/lldb/Host/windows/HostProcessWindows.h
  include/lldb/Host/windows/ProcessLauncherWindows.h
  include/lldb/Target/ProcessLaunchInfo.h
  include/lldb/lldb-defines.h
  include/lldb/lldb-types.h
  source/Host/CMakeLists.txt
  source/Host/common/Host.cpp
  source/Host/common/HostProcess.cpp
  source/Host/common/MonitoringProcessLauncher.cpp
  source/Host/macosx/Host.mm
  source/Host/posix/HostProcessPosix.cpp
  source/Host/posix/ProcessLauncherPosix.cpp
  source/Host/windows/Host.cpp
  source/Host/windows/HostProcessWindows.cpp
  source/Host/windows/ProcessLauncherWindows.cpp
  source/Plugins/Process/Windows/ProcessWindows.cpp
Index: include/lldb/Host/Host.h
===================================================================
--- include/lldb/Host/Host.h
+++ include/lldb/Host/Host.h
@@ -236,11 +236,9 @@
     GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
 
 #if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined (__NetBSD__)
-    static short
-    GetPosixspawnFlags (ProcessLaunchInfo &launch_info);
+    static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info);
 
-    static Error
-    LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid);
+    static Error LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid);
 
     static bool AddPosixSpawnFileAction(void *file_actions, const FileAction *info, Log *log, Error &error);
 #endif
Index: include/lldb/Host/HostNativeProcessBase.h
===================================================================
--- include/lldb/Host/HostNativeProcessBase.h
+++ include/lldb/Host/HostNativeProcessBase.h
@@ -11,18 +11,24 @@
 #define lldb_Host_HostNativeProcessBase_h_
 
 #include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
 #include "lldb/lldb-defines.h"
 #include "lldb/lldb-types.h"
 
 namespace lldb_private
 {
 
+class HostThread;
+
 class HostNativeProcessBase
 {
     DISALLOW_COPY_AND_ASSIGN(HostNativeProcessBase);
 
   public:
-    HostNativeProcessBase() {}
+    HostNativeProcessBase()
+        : m_process(LLDB_INVALID_PROCESS)
+    {
+    }
     explicit HostNativeProcessBase(lldb::process_t process)
         : m_process(process)
     {}
@@ -34,6 +40,8 @@
     virtual lldb::pid_t GetProcessId() const = 0;
     virtual bool IsRunning() const = 0;
 
+    virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) = 0;
+
   protected:
     lldb::process_t m_process;
 };
Index: include/lldb/Host/HostProcess.h
===================================================================
--- include/lldb/Host/HostProcess.h
+++ include/lldb/Host/HostProcess.h
@@ -32,10 +32,13 @@
 {
 
 class HostNativeProcessBase;
+class HostThread;
 
 class HostProcess
 {
   public:
+    typedef bool (*MonitorCallback)(void *callback_baton, lldb::pid_t process, bool exited, int signal, int status);
+
     HostProcess();
     HostProcess(lldb::process_t process);
     ~HostProcess();
@@ -46,6 +49,8 @@
     lldb::pid_t GetProcessId() const;
     bool IsRunning() const;
 
+    HostThread StartMonitoring(MonitorCallback callback, void *callback_baton, bool monitor_signals);
+
     HostNativeProcessBase &GetNativeProcess();
     const HostNativeProcessBase &GetNativeProcess() const;
 
Index: include/lldb/Host/MonitoringProcessLauncher.h
===================================================================
--- /dev/null
+++ include/lldb/Host/MonitoringProcessLauncher.h
@@ -0,0 +1,30 @@
+//===-- MonitoringProcessLauncher.h -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Host_MonitoringProcessLauncher_h_
+#define lldb_Host_MonitoringProcessLauncher_h_
+
+#include "lldb/Host/ProcessLauncher.h"
+
+namespace lldb_private
+{
+
+class MonitoringProcessLauncher : public ProcessLauncher
+{
+  public:
+    explicit MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher);
+
+    virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
+
+  private:
+    std::unique_ptr<ProcessLauncher> m_delegate_launcher;
+};
+}
+
+#endif
Index: include/lldb/Host/ProcessLauncher.h
===================================================================
--- /dev/null
+++ include/lldb/Host/ProcessLauncher.h
@@ -0,0 +1,28 @@
+//===-- ProcessLauncher.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Host_ProcessLauncher_h_
+#define lldb_Host_ProcessLauncher_h_
+
+namespace lldb_private
+{
+
+class ProcessLaunchInfo;
+class Error;
+class HostProcess;
+
+class ProcessLauncher
+{
+  public:
+    virtual ~ProcessLauncher() {}
+    virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) = 0;
+};
+}
+
+#endif
Index: include/lldb/Host/posix/HostProcessPosix.h
===================================================================
--- include/lldb/Host/posix/HostProcessPosix.h
+++ include/lldb/Host/posix/HostProcessPosix.h
@@ -34,6 +34,8 @@
 
     virtual lldb::pid_t GetProcessId() const;
     virtual bool IsRunning() const;
+
+    virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals);
 };
 }
 
Index: include/lldb/Host/posix/ProcessLauncherPosix.h
===================================================================
--- /dev/null
+++ include/lldb/Host/posix/ProcessLauncherPosix.h
@@ -0,0 +1,25 @@
+//===-- ProcessLauncherPosix.h ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Host_posix_ProcessLauncherPosix_h_
+#define lldb_Host_posix_ProcessLauncherPosix_h_
+
+#include "lldb/Host/ProcessLauncher.h"
+
+namespace lldb_private
+{
+
+class ProcessLauncherPosix : public ProcessLauncher
+{
+  public:
+    virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
+};
+}
+
+#endif
Index: include/lldb/Host/windows/HostProcessWindows.h
===================================================================
--- include/lldb/Host/windows/HostProcessWindows.h
+++ include/lldb/Host/windows/HostProcessWindows.h
@@ -11,6 +11,7 @@
 #define lldb_Host_HostProcessWindows_h_
 
 #include "lldb/Host/HostNativeProcessBase.h"
+#include "lldb/lldb-types.h"
 
 namespace lldb_private
 {
@@ -30,7 +31,11 @@
     virtual lldb::pid_t GetProcessId() const;
     virtual bool IsRunning() const;
 
+    virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals);
+
   private:
+    static lldb::thread_result_t MonitorThread(void *thread_arg);
+
     void Close();
 };
 }
Index: include/lldb/Host/windows/ProcessLauncherWindows.h
===================================================================
--- /dev/null
+++ include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -0,0 +1,31 @@
+//===-- ProcessLauncherWindows.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Host_windows_ProcessLauncherWindows_h_
+#define lldb_Host_windows_ProcessLauncherWindows_h_
+
+#include "lldb/Host/ProcessLauncher.h"
+#include "lldb/Host/windows/windows.h"
+
+namespace lldb_private
+{
+
+class ProcessLaunchInfo;
+
+class ProcessLauncherWindows : public ProcessLauncher
+{
+  public:
+    virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
+
+  protected:
+    HANDLE GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd);
+};
+}
+
+#endif
Index: include/lldb/Target/ProcessLaunchInfo.h
===================================================================
--- include/lldb/Target/ProcessLaunchInfo.h
+++ include/lldb/Target/ProcessLaunchInfo.h
@@ -124,7 +124,7 @@
         }
 
         bool
-        GetLaunchInSeparateProcessGroup ()
+        GetLaunchInSeparateProcessGroup() const
         {
             return m_flags.Test(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
         }
@@ -148,17 +148,23 @@
                                    bool monitor_signals);
 
         Host::MonitorChildProcessCallback
-        GetMonitorProcessCallback ()
+        GetMonitorProcessCallback() const
         {
             return m_monitor_callback;
         }
 
-        const void*
-        GetMonitorProcessBaton () const
+        void *
+        GetMonitorProcessBaton() const
         {
             return m_monitor_callback_baton;
         }
 
+        bool
+        GetMonitorSignals() const
+        {
+            return m_monitor_signals;
+        }
+
         // If the LaunchInfo has a monitor callback, then arrange to monitor the process.
         // Return true if the LaunchInfo has taken care of monitoring the process, and false if the
         // caller might want to monitor the process themselves.
Index: include/lldb/lldb-defines.h
===================================================================
--- include/lldb/lldb-defines.h
+++ include/lldb/lldb-defines.h
@@ -49,7 +49,11 @@
 // LLDB defines
 //----------------------------------------------------------------------
 #define LLDB_GENERIC_ERROR              UINT32_MAX
+#if defined(_WIN32)
+#define LLDB_DEFAULT_SHELL              "cmd.exe"
+#else
 #define LLDB_DEFAULT_SHELL              "/bin/sh"
+#endif
 
 //----------------------------------------------------------------------
 // Breakpoints
Index: include/lldb/lldb-types.h
===================================================================
--- include/lldb/lldb-types.h
+++ include/lldb/lldb-types.h
@@ -95,6 +95,7 @@
     typedef bool                (*ExpressionCancelCallback) (ExpressionEvaluationPhase phase, void *baton);
 }
 
+#define LLDB_INVALID_PROCESS             ((lldb::process_t)-1)
 #define LLDB_INVALID_HOST_THREAD         ((lldb::thread_t)NULL)
 #define IS_VALID_LLDB_HOST_THREAD(t)     ((t) != LLDB_INVALID_HOST_THREAD)
 
Index: source/Host/CMakeLists.txt
===================================================================
--- source/Host/CMakeLists.txt
+++ source/Host/CMakeLists.txt
@@ -16,6 +16,7 @@
   common/HostThread.cpp
   common/IOObject.cpp
   common/Mutex.cpp
+  common/MonitoringProcessLauncher.cpp
   common/NativeBreakpoint.cpp
   common/NativeBreakpointList.cpp
   common/NativeProcessProtocol.cpp
@@ -48,6 +49,7 @@
     windows/HostThreadWindows.cpp
     windows/Mutex.cpp
     windows/PipeWindows.cpp
+    windows/ProcessLauncherWindows.cpp
     windows/ProcessRunLock.cpp
     windows/ThisThread.cpp
     windows/Windows.cpp
@@ -59,6 +61,7 @@
     posix/HostProcessPosix.cpp
     posix/HostThreadPosix.cpp
     posix/PipePosix.cpp
+    posix/ProcessLauncherPosix.cpp
     )
 
   if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
Index: source/Host/common/Host.cpp
===================================================================
--- source/Host/common/Host.cpp
+++ source/Host/common/Host.cpp
@@ -71,7 +71,10 @@
 #include "lldb/Host/Endian.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/MonitoringProcessLauncher.h"
 #include "lldb/Host/Mutex.h"
+#include "lldb/Host/ProcessLauncher.h"
 #include "lldb/Host/ThreadLauncher.h"
 #include "lldb/lldb-private-forward.h"
 #include "lldb/Target/FileAction.h"
@@ -86,6 +89,12 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 
+#if defined(_WIN32)
+#include "lldb/Host/windows/ProcessLauncherWindows.h"
+#else
+#include "lldb/Host/posix/ProcessLauncherPosix.h"
+#endif
+
 #if defined (__APPLE__)
 #ifndef _POSIX_SPAWN_DISABLE_ASLR
 #define _POSIX_SPAWN_DISABLE_ASLR       0x0100
@@ -717,7 +726,7 @@
 // common/Host.cpp.
 
 short
-Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info)
+Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info)
 {
 #ifndef __ANDROID__
     short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
@@ -769,7 +778,7 @@
 }
 
 Error
-Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
+Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
 {
     Error error;
 #ifndef __ANDROID__
@@ -890,6 +899,7 @@
 #endif
     }
 
+    ::pid_t result_pid;
     const size_t num_file_actions = launch_info.GetNumFileActions ();
     if (num_file_actions > 0)
     {
@@ -914,21 +924,13 @@
             }
         }
 
-        error.SetError (::posix_spawnp (&pid,
-                                        exe_path,
-                                        &file_actions,
-                                        &attr,
-                                        argv,
-                                        envp),
-                        eErrorTypePOSIX);
+        error.SetError(::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX);
 
         if (error.Fail() || log)
         {
-            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
-                           pid, exe_path, static_cast<void*>(&file_actions),
-                           static_cast<void*>(&attr),
-                           reinterpret_cast<const void*>(argv),
-                           reinterpret_cast<const void*>(envp));
+            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid,
+                           exe_path, static_cast<void *>(&file_actions), static_cast<void *>(&attr), reinterpret_cast<const void *>(argv),
+                           reinterpret_cast<const void *>(envp));
             if (log)
             {
                 for (int ii=0; argv[ii]; ++ii)
@@ -939,27 +941,21 @@
     }
     else
     {
-        error.SetError (::posix_spawnp (&pid,
-                                        exe_path,
-                                        NULL,
-                                        &attr,
-                                        argv,
-                                        envp),
-                        eErrorTypePOSIX);
+        error.SetError(::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX);
 
         if (error.Fail() || log)
         {
             error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
-                           pid, exe_path, static_cast<void*>(&attr),
-                           reinterpret_cast<const void*>(argv),
-                           reinterpret_cast<const void*>(envp));
+                           result_pid, exe_path, static_cast<void *>(&attr), reinterpret_cast<const void *>(argv),
+                           reinterpret_cast<const void *>(envp));
             if (log)
             {
                 for (int ii=0; argv[ii]; ++ii)
                     log->Printf("argv[%i] = '%s'", ii, argv[ii]);
             }
         }
     }
+    pid = result_pid;
 
     if (working_dir)
     {
@@ -1056,86 +1052,28 @@
 
 #endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems
 
-
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) || defined(_WIN32)
 // The functions below implement process launching via posix_spawn() for Linux,
 // FreeBSD and NetBSD.
 
 Error
 Host::LaunchProcess (ProcessLaunchInfo &launch_info)
 {
-    Error error;
-    char exe_path[PATH_MAX];
-
-    PlatformSP host_platform_sp (Platform::GetHostPlatform ());
-
-    const ArchSpec &arch_spec = launch_info.GetArchitecture();
-
-    FileSpec exe_spec(launch_info.GetExecutableFile());
-
-    FileSpec::FileType file_type = exe_spec.GetFileType();
-    if (file_type != FileSpec::eFileTypeRegular)
-    {
-        lldb::ModuleSP exe_module_sp;
-        error = host_platform_sp->ResolveExecutable (exe_spec,
-                                                     arch_spec,
-                                                     exe_module_sp,
-                                                     NULL);
-
-        if (error.Fail())
-            return error;
-
-        if (exe_module_sp)
-            exe_spec = exe_module_sp->GetFileSpec();
-    }
-
-    if (exe_spec.Exists())
-    {
-        exe_spec.GetPath (exe_path, sizeof(exe_path));
-    }
-    else
-    {
-        launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path));
-        error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path);
-        return error;
-    }
-
-    assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY));
-
-    ::pid_t pid = LLDB_INVALID_PROCESS_ID;
-
-    error = LaunchProcessPosixSpawn(exe_path, launch_info, pid);
+    std::unique_ptr<ProcessLauncher> delegate_launcher;
+#if defined(_WIN32)
+    delegate_launcher.reset(new ProcessLauncherWindows());
+#else
+    delegate_launcher.reset(new ProcessLauncherPosix());
+#endif
+    MonitoringProcessLauncher launcher(std::move(delegate_launcher));
 
-    if (pid != LLDB_INVALID_PROCESS_ID)
-    {
-        // If all went well, then set the process ID into the launch info
-        launch_info.SetProcessID(pid);
+    Error error;
+    HostProcess process = launcher.LaunchProcess(launch_info, error);
 
-        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+    // TODO(zturner): It would be better if the entire HostProcess were returned instead of writing
+    // it into this structure.
+    launch_info.SetProcessID(process.GetProcessId());
 
-        // Make sure we reap any processes we spawn or we will have zombies.
-        if (!launch_info.MonitorProcess())
-        {
-            const bool monitor_signals = false;
-            StartMonitoringChildProcess (Process::SetProcessExitStatus,
-                                         NULL,
-                                         pid,
-                                         monitor_signals);
-            if (log)
-                log->PutCString ("monitored child process with default Process::SetProcessExitStatus.");
-        }
-        else
-        {
-            if (log)
-                log->PutCString ("monitored child process with user-specified process monitor.");
-        }
-    }
-    else
-    {
-        // Invalid process ID, something didn't go well
-        if (error.Success())
-            error.SetErrorString ("process launch failed for unknown reasons");
-    }
     return error;
 }
 
Index: source/Host/common/HostProcess.cpp
===================================================================
--- source/Host/common/HostProcess.cpp
+++ source/Host/common/HostProcess.cpp
@@ -9,6 +9,7 @@
 
 #include "lldb/Host/HostNativeProcess.h"
 #include "lldb/Host/HostProcess.h"
+#include "lldb/Host/HostThread.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -47,6 +48,12 @@
     return m_native_process->IsRunning();
 }
 
+HostThread
+HostProcess::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals)
+{
+    return m_native_process->StartMonitoring(callback, callback_baton, monitor_signals);
+}
+
 HostNativeProcessBase &HostProcess::GetNativeProcess()
 {
     return *m_native_process;
Index: source/Host/common/MonitoringProcessLauncher.cpp
===================================================================
--- /dev/null
+++ source/Host/common/MonitoringProcessLauncher.cpp
@@ -0,0 +1,102 @@
+//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/MonitoringProcessLauncher.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher)
+    : m_delegate_launcher(std::move(delegate_launcher))
+{
+}
+
+HostProcess
+MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
+{
+    ProcessLaunchInfo resolved_info(launch_info);
+
+    error.Clear();
+    char exe_path[PATH_MAX];
+
+    PlatformSP host_platform_sp(Platform::GetHostPlatform());
+
+    const ArchSpec &arch_spec = resolved_info.GetArchitecture();
+
+    FileSpec exe_spec(resolved_info.GetExecutableFile());
+
+    FileSpec::FileType file_type = exe_spec.GetFileType();
+    if (file_type != FileSpec::eFileTypeRegular)
+    {
+        lldb::ModuleSP exe_module_sp;
+        error = host_platform_sp->ResolveExecutable(exe_spec, arch_spec, exe_module_sp, NULL);
+
+        if (error.Fail())
+            return HostProcess();
+
+        if (exe_module_sp)
+            exe_spec = exe_module_sp->GetFileSpec();
+    }
+
+    if (exe_spec.Exists())
+    {
+        exe_spec.GetPath(exe_path, sizeof(exe_path));
+    }
+    else
+    {
+        resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
+        error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path);
+        return HostProcess();
+    }
+
+    resolved_info.SetExecutableFile(exe_spec, false);
+    assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY));
+
+    ::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+    HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error);
+
+    if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID)
+    {
+        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+        Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback();
+
+        void *baton = nullptr;
+        bool monitor_signals = false;
+        if (callback)
+        {
+            // If the ProcessLaunchInfo specified a callback, use that.
+            baton = launch_info.GetMonitorProcessBaton();
+            monitor_signals = launch_info.GetMonitorSignals();
+        }
+        else
+        {
+            callback = Process::SetProcessExitStatus;
+        }
+
+        process.StartMonitoring(callback, baton, monitor_signals);
+        if (log)
+            log->PutCString("started monitoring child process.");
+    }
+    else
+    {
+        // Invalid process ID, something didn't go well
+        if (error.Success())
+            error.SetErrorString("process launch failed for unknown reasons");
+    }
+    return process;
+}
Index: source/Host/macosx/Host.mm
===================================================================
--- source/Host/macosx/Host.mm
+++ source/Host/macosx/Host.mm
@@ -1138,7 +1138,7 @@
 #endif
 
 static Error
-LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
+LaunchProcessXPC(const char *exe_path, ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
 {
 #if !NO_XPC_SERVICES
     Error error = getXPCAuthorization(launch_info);
@@ -1347,9 +1347,9 @@
         return error;
 #endif
     }
-    
-    ::pid_t pid = LLDB_INVALID_PROCESS_ID;
-    
+
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
     if (ShouldLaunchUsingXPC(launch_info))
     {
         error = LaunchProcessXPC(exe_path, launch_info, pid);
Index: source/Host/posix/HostProcessPosix.cpp
===================================================================
--- source/Host/posix/HostProcessPosix.cpp
+++ source/Host/posix/HostProcessPosix.cpp
@@ -1,12 +1,13 @@
-//===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===//
+//===-- HostProcessPosix.cpp ------------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/Host/Host.h"
 #include "lldb/Host/posix/HostProcessPosix.h"
 #include "lldb/Host/FileSystem.h"
 
@@ -107,3 +108,9 @@
     Error error = Signal(0);
     return error.Success();
 }
+
+HostThread
+HostProcessPosix::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals)
+{
+    return Host::StartMonitoringChildProcess(callback, callback_baton, m_process, monitor_signals);
+}
Index: source/Host/posix/ProcessLauncherPosix.cpp
===================================================================
--- /dev/null
+++ source/Host/posix/ProcessLauncherPosix.cpp
@@ -0,0 +1,33 @@
+//===-- ProcessLauncherPosix.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/posix/ProcessLauncherPosix.h"
+
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+#include <limits.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+HostProcess
+ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
+{
+    lldb::pid_t pid;
+    char exe_path[PATH_MAX];
+
+    launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
+
+    // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make MacOSX re-use this
+    // ProcessLauncher when it wants a posix_spawn launch.
+    error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid);
+    return HostProcess(pid);
+}
Index: source/Host/windows/Host.cpp
===================================================================
--- source/Host/windows/Host.cpp
+++ source/Host/windows/Host.cpp
@@ -96,14 +96,6 @@
     }
 }
 
-Error
-Host::LaunchProcess (ProcessLaunchInfo &launch_info)
-{
-    Error error;
-    assert(!"Not implemented yet!!!");
-    return error;
-}
-
 lldb::DataBufferSP
 Host::GetAuxvData(lldb_private::Process *process)
 {
Index: source/Host/windows/HostProcessWindows.cpp
===================================================================
--- source/Host/windows/HostProcessWindows.cpp
+++ source/Host/windows/HostProcessWindows.cpp
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/FileSpec.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/ThreadLauncher.h"
 #include "lldb/Host/windows/windows.h"
 #include "lldb/Host/windows/HostProcessWindows.h"
 
@@ -17,6 +19,16 @@
 
 using namespace lldb_private;
 
+namespace
+{
+struct MonitorInfo
+{
+    HostProcess::MonitorCallback callback;
+    void *baton;
+    HANDLE process_handle;
+};
+}
+
 HostProcessWindows::HostProcessWindows()
     : HostNativeProcessBase()
 {
@@ -61,7 +73,7 @@
 
 lldb::pid_t HostProcessWindows::GetProcessId() const
 {
-    return ::GetProcessId(m_process);
+    return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);
 }
 
 bool HostProcessWindows::IsRunning() const
@@ -76,9 +88,42 @@
     return (code == STILL_ACTIVE);
 }
 
+HostThread
+HostProcessWindows::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals)
+{
+    HostThread monitor_thread;
+    MonitorInfo *info = new MonitorInfo;
+    info->callback = callback;
+    info->baton = callback_baton;
+
+    // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that
+    // the monitor thread can have ownership over its own copy of the handle.
+    HostThread result;
+    if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
+        result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr);
+    return result;
+}
+
+lldb::thread_result_t
+HostProcessWindows::MonitorThread(void *thread_arg)
+{
+    DWORD exit_code;
+
+    MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg);
+    if (info)
+    {
+        DWORD wait_result = ::WaitForSingleObject(info->process_handle, INFINITE);
+        ::GetExitCodeProcess(info->process_handle, &exit_code);
+        info->callback(info->baton, ::GetProcessId(info->process_handle), true, 0, exit_code);
+
+        delete (info);
+    }
+    return 0;
+}
+
 void HostProcessWindows::Close()
 {
-    if (m_process != nullptr)
+    if (m_process != LLDB_INVALID_PROCESS)
         ::CloseHandle(m_process);
     m_process = nullptr;
 }
Index: source/Host/windows/ProcessLauncherWindows.cpp
===================================================================
--- /dev/null
+++ source/Host/windows/ProcessLauncherWindows.cpp
@@ -0,0 +1,94 @@
+//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/windows/ProcessLauncherWindows.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+#include <string>
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+HostProcess
+ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
+{
+    error.Clear();
+
+    std::string executable;
+    std::string commandLine;
+    std::vector<char> environment;
+    STARTUPINFO startupinfo = {0};
+    PROCESS_INFORMATION pi = {0};
+
+    HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
+    HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
+    HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
+
+    startupinfo.cb = sizeof(startupinfo);
+    startupinfo.dwFlags |= STARTF_USESTDHANDLES;
+    startupinfo.hStdError = stderr_handle;
+    startupinfo.hStdInput = stdin_handle;
+    startupinfo.hStdOutput = stdout_handle;
+
+    executable = launch_info.GetExecutableFile().GetPath();
+    launch_info.GetArguments().GetQuotedCommandString(commandLine);
+    BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL,
+                                   launch_info.GetWorkingDirectory(), &startupinfo, &pi);
+    if (result)
+    {
+        // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
+        ::CloseHandle(pi.hThread);
+    }
+
+    if (stdin_handle)
+        ::CloseHandle(stdin_handle);
+    if (stdout_handle)
+        ::CloseHandle(stdout_handle);
+    if (stderr_handle)
+        ::CloseHandle(stderr_handle);
+
+    if (!result)
+        error.SetError(::GetLastError(), eErrorTypeWin32);
+    return HostProcess(pi.hProcess);
+}
+
+HANDLE
+ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd)
+{
+    const FileAction *action = launch_info.GetFileActionForFD(fd);
+    if (action == nullptr)
+        return NULL;
+    SECURITY_ATTRIBUTES secattr = {0};
+    secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+    secattr.bInheritHandle = TRUE;
+
+    const char *path = action->GetPath();
+    DWORD access = 0;
+    DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
+    DWORD create = 0;
+    DWORD flags = 0;
+    if (fd == STDIN_FILENO)
+    {
+        access = GENERIC_READ;
+        create = OPEN_EXISTING;
+        flags = FILE_ATTRIBUTE_READONLY;
+    }
+    if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
+    {
+        access = GENERIC_WRITE;
+        create = CREATE_ALWAYS;
+        if (fd == STDERR_FILENO)
+            flags = FILE_FLAG_WRITE_THROUGH;
+    }
+
+    HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
+    return (result == INVALID_HANDLE_VALUE) ? NULL : result;
+}
Index: source/Plugins/Process/Windows/ProcessWindows.cpp
===================================================================
--- source/Plugins/Process/Windows/ProcessWindows.cpp
+++ source/Plugins/Process/Windows/ProcessWindows.cpp
@@ -16,6 +16,8 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/State.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/windows/ProcessLauncherWindows.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/FileAction.h"
@@ -26,42 +28,6 @@
 using namespace lldb;
 using namespace lldb_private;
 
-namespace
-{
-HANDLE
-GetStdioHandle(ProcessLaunchInfo &launch_info, int fd)
-{
-    const FileAction *action = launch_info.GetFileActionForFD(fd);
-    if (action == nullptr)
-        return NULL;
-    SECURITY_ATTRIBUTES secattr = {0};
-    secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
-    secattr.bInheritHandle = TRUE;
-
-    const char *path = action->GetPath();
-    DWORD access = 0;
-    DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
-    DWORD create = 0;
-    DWORD flags = 0;
-    if (fd == STDIN_FILENO)
-    {
-        access = GENERIC_READ;
-        create = OPEN_EXISTING;
-        flags = FILE_ATTRIBUTE_READONLY;
-    }
-    if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
-    {
-        access = GENERIC_WRITE;
-        create = CREATE_ALWAYS;
-        if (fd == STDERR_FILENO)
-            flags = FILE_FLAG_WRITE_THROUGH;
-    }
-
-    HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
-    return (result == INVALID_HANDLE_VALUE) ? NULL : result;
-}
-}
-
 //------------------------------------------------------------------------------
 // Static functions.
 
@@ -123,42 +89,10 @@
 ProcessWindows::DoLaunch(Module *exe_module,
                          ProcessLaunchInfo &launch_info)
 {
-    std::string executable;
-    std::string commandLine;
-    std::vector<char> environment;
-    STARTUPINFO startupinfo = {0};
-    PROCESS_INFORMATION pi = {0};
-
-    HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
-    HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
-    HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
-
-    startupinfo.cb = sizeof(startupinfo);
-    startupinfo.dwFlags |= STARTF_USESTDHANDLES;
-    startupinfo.hStdError = stderr_handle;
-    startupinfo.hStdInput = stdin_handle;
-    startupinfo.hStdOutput = stdout_handle;
-
-    executable = launch_info.GetExecutableFile().GetPath();
-    launch_info.GetArguments().GetQuotedCommandString(commandLine);
-    BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE,
-                                   CREATE_NEW_CONSOLE, NULL, launch_info.GetWorkingDirectory(), &startupinfo, &pi);
-    if (result)
-    {
-        ::CloseHandle(pi.hProcess);
-        ::CloseHandle(pi.hThread);
-    }
-
-    if (stdin_handle)
-        ::CloseHandle(stdin_handle);
-    if (stdout_handle)
-        ::CloseHandle(stdout_handle);
-    if (stderr_handle)
-        ::CloseHandle(stderr_handle);
-
     Error error;
-    if (!result)
-        error.SetErrorToErrno();
+    ProcessLauncherWindows launcher;
+    HostProcess process = launcher.LaunchProcess(launch_info, error);
+    launch_info.SetProcessID(process.GetProcessId());
     return error;
 }
 
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to