diff options
Diffstat (limited to 'lldb/source/Host/windows')
-rw-r--r-- | lldb/source/Host/windows/Host.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Host/windows/HostProcessWindows.cpp | 49 | ||||
-rw-r--r-- | lldb/source/Host/windows/ProcessLauncherWindows.cpp | 94 |
3 files changed, 141 insertions, 10 deletions
diff --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp index 4542025f6ee..4f698df16eb 100644 --- a/lldb/source/Host/windows/Host.cpp +++ b/lldb/source/Host/windows/Host.cpp @@ -96,14 +96,6 @@ namespace } } -Error -Host::LaunchProcess (ProcessLaunchInfo &launch_info) -{ - Error error; - assert(!"Not implemented yet!!!"); - return error; -} - lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { diff --git a/lldb/source/Host/windows/HostProcessWindows.cpp b/lldb/source/Host/windows/HostProcessWindows.cpp index 447f672ac77..8388e21b853 100644 --- a/lldb/source/Host/windows/HostProcessWindows.cpp +++ b/lldb/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 @@ Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const 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 @@ 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; } diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp new file mode 100644 index 00000000000..7a99e0944e5 --- /dev/null +++ b/lldb/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; +} |