180814287SRaphael Isemann //===-- HostProcessWindows.cpp --------------------------------------------===//
24e82ec9cSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64e82ec9cSZachary Turner //
74e82ec9cSZachary Turner //===----------------------------------------------------------------------===//
84e82ec9cSZachary Turner
9b9c1b51eSKate Stone #include "lldb/Host/windows/HostProcessWindows.h"
10172d37d3SZachary Turner #include "lldb/Host/HostThread.h"
11172d37d3SZachary Turner #include "lldb/Host/ThreadLauncher.h"
124e82ec9cSZachary Turner #include "lldb/Host/windows/windows.h"
135713a05bSZachary Turner #include "lldb/Utility/FileSpec.h"
144e82ec9cSZachary Turner
154e82ec9cSZachary Turner #include "llvm/ADT/STLExtras.h"
16190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
17631b5f7dSStella Stamenova #include "llvm/Support/WindowsError.h"
184e82ec9cSZachary Turner
19f6ee79c9SHafiz Abid Qadeer #include <psapi.h>
20f5e4f37cSZachary Turner
214e82ec9cSZachary Turner using namespace lldb_private;
224e82ec9cSZachary Turner
23b9c1b51eSKate Stone namespace {
24b9c1b51eSKate Stone struct MonitorInfo {
25998bdc5bSPavel Labath Host::MonitorChildProcessCallback callback;
26172d37d3SZachary Turner HANDLE process_handle;
27172d37d3SZachary Turner };
28172d37d3SZachary Turner }
29172d37d3SZachary Turner
HostProcessWindows()30c76a4452SZachary Turner HostProcessWindows::HostProcessWindows()
31b9c1b51eSKate Stone : HostNativeProcessBase(), m_owns_handle(true) {}
32c76a4452SZachary Turner
HostProcessWindows(lldb::process_t process)33f5e4f37cSZachary Turner HostProcessWindows::HostProcessWindows(lldb::process_t process)
34b9c1b51eSKate Stone : HostNativeProcessBase(process), m_owns_handle(true) {}
354e82ec9cSZachary Turner
~HostProcessWindows()36b9c1b51eSKate Stone HostProcessWindows::~HostProcessWindows() { Close(); }
374e82ec9cSZachary Turner
SetOwnsHandle(bool owns)38b9c1b51eSKate Stone void HostProcessWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; }
39742346a2SZachary Turner
Terminate()4097206d57SZachary Turner Status HostProcessWindows::Terminate() {
4197206d57SZachary Turner Status error;
42f5e4f37cSZachary Turner if (m_process == nullptr)
434e82ec9cSZachary Turner error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
444e82ec9cSZachary Turner
454e82ec9cSZachary Turner if (!::TerminateProcess(m_process, 0))
464e82ec9cSZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
474e82ec9cSZachary Turner
484e82ec9cSZachary Turner return error;
494e82ec9cSZachary Turner }
504e82ec9cSZachary Turner
GetProcessId() const51b9c1b51eSKate Stone lldb::pid_t HostProcessWindows::GetProcessId() const {
52172d37d3SZachary Turner return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);
534e82ec9cSZachary Turner }
544e82ec9cSZachary Turner
IsRunning() const55b9c1b51eSKate Stone bool HostProcessWindows::IsRunning() const {
56f5e4f37cSZachary Turner if (m_process == nullptr)
574e82ec9cSZachary Turner return false;
584e82ec9cSZachary Turner
594e82ec9cSZachary Turner DWORD code = 0;
604e82ec9cSZachary Turner if (!::GetExitCodeProcess(m_process, &code))
614e82ec9cSZachary Turner return false;
624e82ec9cSZachary Turner
634e82ec9cSZachary Turner return (code == STILL_ACTIVE);
644e82ec9cSZachary Turner }
654e82ec9cSZachary Turner
6682951cfbSPavel Labath static lldb::thread_result_t
MonitorThread(const Host::MonitorChildProcessCallback & callback,HANDLE process_handle)6782951cfbSPavel Labath MonitorThread(const Host::MonitorChildProcessCallback &callback,
6882951cfbSPavel Labath HANDLE process_handle) {
6982951cfbSPavel Labath DWORD exit_code;
7082951cfbSPavel Labath
7182951cfbSPavel Labath ::WaitForSingleObject(process_handle, INFINITE);
7282951cfbSPavel Labath ::GetExitCodeProcess(process_handle, &exit_code);
73*b5eeb887SPavel Labath callback(::GetProcessId(process_handle), 0, exit_code);
7482951cfbSPavel Labath ::CloseHandle(process_handle);
7582951cfbSPavel Labath return {};
7682951cfbSPavel Labath }
7782951cfbSPavel Labath
StartMonitoring(const Host::MonitorChildProcessCallback & callback)7809923183SJonas Devlieghere llvm::Expected<HostThread> HostProcessWindows::StartMonitoring(
7912c9c4a8SPavel Labath const Host::MonitorChildProcessCallback &callback) {
8082951cfbSPavel Labath HANDLE process_handle;
81172d37d3SZachary Turner
82b9c1b51eSKate Stone // Since the life of this HostProcessWindows instance and the life of the
8305097246SAdrian Prantl // process may be different, duplicate the handle so that the monitor thread
8405097246SAdrian Prantl // can have ownership over its own copy of the handle.
85b9c1b51eSKate Stone if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(),
8682951cfbSPavel Labath &process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
8782951cfbSPavel Labath return ThreadLauncher::LaunchThread(
8882951cfbSPavel Labath "ChildProcessMonitor", [callback, process_handle] {
8982951cfbSPavel Labath return MonitorThread(callback, process_handle);
9082951cfbSPavel Labath });
917f843e22SStella Stamenova } else {
92631b5f7dSStella Stamenova return llvm::errorCodeToError(llvm::mapWindowsError(GetLastError()));
937f843e22SStella Stamenova }
94172d37d3SZachary Turner }
95172d37d3SZachary Turner
Close()96b9c1b51eSKate Stone void HostProcessWindows::Close() {
97742346a2SZachary Turner if (m_owns_handle && m_process != LLDB_INVALID_PROCESS)
984e82ec9cSZachary Turner ::CloseHandle(m_process);
994e82ec9cSZachary Turner m_process = nullptr;
1004e82ec9cSZachary Turner }
101