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
#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)
{}
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;
};
{
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();
lldb::pid_t GetProcessId() const;
bool IsRunning() const;
+ HostThread StartMonitoring(MonitorCallback callback, void *callback_baton, bool monitor_signals);
+
HostNativeProcessBase &GetNativeProcess();
const HostNativeProcessBase &GetNativeProcess() const;
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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
virtual lldb::pid_t GetProcessId() const;
virtual bool IsRunning() const;
+
+ virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals);
};
}
--- /dev/null
+//===-- 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
#define lldb_Host_HostProcessWindows_h_
#include "lldb/Host/HostNativeProcessBase.h"
+#include "lldb/lldb-types.h"
namespace lldb_private
{
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();
};
}
--- /dev/null
+//===-- 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
}
bool
- GetLaunchInSeparateProcessGroup ()
+ GetLaunchInSeparateProcessGroup() const
{
return m_flags.Test(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
}
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.
// 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
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)
common/HostThread.cpp
common/IOObject.cpp
common/Mutex.cpp
+ common/MonitoringProcessLauncher.cpp
common/NativeBreakpoint.cpp
common/NativeBreakpointList.cpp
common/NativeProcessProtocol.cpp
windows/HostThreadWindows.cpp
windows/Mutex.cpp
windows/PipeWindows.cpp
+ windows/ProcessLauncherWindows.cpp
windows/ProcessRunLock.cpp
windows/ThisThread.cpp
windows/Windows.cpp
posix/HostProcessPosix.cpp
posix/HostThreadPosix.cpp
posix/PipePosix.cpp
+ posix/ProcessLauncherPosix.cpp
)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
#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"
#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
// 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;
}
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__
#endif
}
+ ::pid_t result_pid = LLDB_INVALID_PROCESS_ID;
const size_t num_file_actions = launch_info.GetNumFileActions ();
if (num_file_actions > 0)
{
}
}
- 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)
}
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)
}
}
}
+ pid = result_pid;
if (working_dir)
{
#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;
}
#include "lldb/Host/HostNativeProcess.h"
#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/HostThread.h"
using namespace lldb;
using namespace lldb_private;
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;
--- /dev/null
+//===-- 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;
+}
#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);
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);
-//===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===//
+//===-- HostProcessPosix.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
+#include "lldb/Host/Host.h"
#include "lldb/Host/posix/HostProcessPosix.h"
#include "lldb/Host/FileSystem.h"
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);
+}
--- /dev/null
+//===-- 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);
+}
}
}
-Error
-Host::LaunchProcess (ProcessLaunchInfo &launch_info)
-{
- Error error;
- assert(!"Not implemented yet!!!");
- return error;
-}
-
lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
{
//===----------------------------------------------------------------------===//
#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"
using namespace lldb_private;
+namespace
+{
+struct MonitorInfo
+{
+ HostProcess::MonitorCallback callback;
+ void *baton;
+ HANDLE process_handle;
+};
+}
+
HostProcessWindows::HostProcessWindows()
: HostNativeProcessBase()
{
lldb::pid_t HostProcessWindows::GetProcessId() const
{
- return ::GetProcessId(m_process);
+ return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);
}
bool HostProcessWindows::IsRunning() const
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;
}
--- /dev/null
+//===-- 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;
+}
#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"
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.
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;
}