Index: lldb/trunk/include/lldb/Host/Host.h =================================================================== --- lldb/trunk/include/lldb/Host/Host.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/HostNativeProcessBase.h =================================================================== --- lldb/trunk/include/lldb/Host/HostNativeProcessBase.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/HostProcess.h =================================================================== --- lldb/trunk/include/lldb/Host/HostProcess.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/MonitoringProcessLauncher.h =================================================================== --- lldb/trunk/include/lldb/Host/MonitoringProcessLauncher.h +++ lldb/trunk/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 delegate_launcher); + + virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error); + + private: + std::unique_ptr m_delegate_launcher; +}; +} + +#endif Index: lldb/trunk/include/lldb/Host/ProcessLauncher.h =================================================================== --- lldb/trunk/include/lldb/Host/ProcessLauncher.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/posix/HostProcessPosix.h =================================================================== --- lldb/trunk/include/lldb/Host/posix/HostProcessPosix.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/posix/ProcessLauncherPosix.h =================================================================== --- lldb/trunk/include/lldb/Host/posix/ProcessLauncherPosix.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/windows/HostProcessWindows.h =================================================================== --- lldb/trunk/include/lldb/Host/windows/HostProcessWindows.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Host/windows/ProcessLauncherWindows.h =================================================================== --- lldb/trunk/include/lldb/Host/windows/ProcessLauncherWindows.h +++ lldb/trunk/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: lldb/trunk/include/lldb/Target/ProcessLaunchInfo.h =================================================================== --- lldb/trunk/include/lldb/Target/ProcessLaunchInfo.h +++ lldb/trunk/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: lldb/trunk/include/lldb/lldb-defines.h =================================================================== --- lldb/trunk/include/lldb/lldb-defines.h +++ lldb/trunk/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: lldb/trunk/include/lldb/lldb-types.h =================================================================== --- lldb/trunk/include/lldb/lldb-types.h +++ lldb/trunk/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: lldb/trunk/source/Host/CMakeLists.txt =================================================================== --- lldb/trunk/source/Host/CMakeLists.txt +++ lldb/trunk/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: lldb/trunk/source/Host/common/Host.cpp =================================================================== --- lldb/trunk/source/Host/common/Host.cpp +++ lldb/trunk/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 = LLDB_INVALID_PROCESS_ID; 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(&file_actions), - static_cast(&attr), - reinterpret_cast(argv), - reinterpret_cast(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(&file_actions), static_cast(&attr), reinterpret_cast(argv), + reinterpret_cast(envp)); if (log) { for (int ii=0; argv[ii]; ++ii) @@ -939,20 +941,13 @@ } 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(&attr), - reinterpret_cast(argv), - reinterpret_cast(envp)); + result_pid, exe_path, static_cast(&attr), reinterpret_cast(argv), + reinterpret_cast(envp)); if (log) { for (int ii=0; argv[ii]; ++ii) @@ -960,6 +955,7 @@ } } } + 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 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: lldb/trunk/source/Host/common/HostProcess.cpp =================================================================== --- lldb/trunk/source/Host/common/HostProcess.cpp +++ lldb/trunk/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: lldb/trunk/source/Host/common/MonitoringProcessLauncher.cpp =================================================================== --- lldb/trunk/source/Host/common/MonitoringProcessLauncher.cpp +++ lldb/trunk/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 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: lldb/trunk/source/Host/macosx/Host.mm =================================================================== --- lldb/trunk/source/Host/macosx/Host.mm +++ lldb/trunk/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: lldb/trunk/source/Host/posix/HostProcessPosix.cpp =================================================================== --- lldb/trunk/source/Host/posix/HostProcessPosix.cpp +++ lldb/trunk/source/Host/posix/HostProcessPosix.cpp @@ -1,4 +1,4 @@ -//===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===// +//===-- HostProcessPosix.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#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: lldb/trunk/source/Host/posix/ProcessLauncherPosix.cpp =================================================================== --- lldb/trunk/source/Host/posix/ProcessLauncherPosix.cpp +++ lldb/trunk/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 + +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: lldb/trunk/source/Host/windows/Host.cpp =================================================================== --- lldb/trunk/source/Host/windows/Host.cpp +++ lldb/trunk/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: lldb/trunk/source/Host/windows/HostProcessWindows.cpp =================================================================== --- lldb/trunk/source/Host/windows/HostProcessWindows.cpp +++ lldb/trunk/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(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: lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp =================================================================== --- lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp +++ lldb/trunk/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 +#include + +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 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(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: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp +++ lldb/trunk/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 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(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; }