summaryrefslogtreecommitdiffstats
path: root/lldb/source/Host/windows
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2014-10-14 21:55:08 +0000
committerZachary Turner <zturner@google.com>2014-10-14 21:55:08 +0000
commit172d37d3b92ca70e65f11f9a7caf7af4c8a5e44f (patch)
tree0df4532b38c6277c18c69659225f56a8188c6092 /lldb/source/Host/windows
parent756acbaa0e76c17426983863099d42449b0a6729 (diff)
downloadbcm5719-llvm-172d37d3b92ca70e65f11f9a7caf7af4c8a5e44f.tar.gz
bcm5719-llvm-172d37d3b92ca70e65f11f9a7caf7af4c8a5e44f.zip
Create a process launcher abstraction.
This implements Host::LaunchProcess for windows, and in doing so does some minor refactor to move towards a more modular process launching design. 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. When launching a process MonitoringProcessLauncher is created, and then an appropriate delegate launcher is created and given to the MonitoringProcessLauncher. Reviewed by: Greg Clayton Differential Revision: http://reviews.llvm.org/D5781 llvm-svn: 219731
Diffstat (limited to 'lldb/source/Host/windows')
-rw-r--r--lldb/source/Host/windows/Host.cpp8
-rw-r--r--lldb/source/Host/windows/HostProcessWindows.cpp49
-rw-r--r--lldb/source/Host/windows/ProcessLauncherWindows.cpp94
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;
+}
OpenPOWER on IntegriCloud