101 lines · cpp
1//===-- HostProcessWindows.cpp --------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/windows/HostProcessWindows.h"10#include "lldb/Host/HostThread.h"11#include "lldb/Host/ThreadLauncher.h"12#include "lldb/Host/windows/windows.h"13#include "lldb/Utility/FileSpec.h"14 15#include "llvm/ADT/STLExtras.h"16#include "llvm/Support/ConvertUTF.h"17#include "llvm/Support/WindowsError.h"18 19#include <psapi.h>20 21using namespace lldb_private;22 23namespace {24struct MonitorInfo {25 Host::MonitorChildProcessCallback callback;26 HANDLE process_handle;27};28}29 30HostProcessWindows::HostProcessWindows()31 : HostNativeProcessBase(), m_owns_handle(true) {}32 33HostProcessWindows::HostProcessWindows(lldb::process_t process)34 : HostNativeProcessBase(process), m_owns_handle(true) {}35 36HostProcessWindows::~HostProcessWindows() { Close(); }37 38void HostProcessWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; }39 40Status HostProcessWindows::Terminate() {41 Status error;42 if (m_process == nullptr)43 error = Status(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);44 45 if (!::TerminateProcess(m_process, 0))46 error = Status(::GetLastError(), lldb::eErrorTypeWin32);47 48 return error;49}50 51lldb::pid_t HostProcessWindows::GetProcessId() const {52 return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);53}54 55bool HostProcessWindows::IsRunning() const {56 if (m_process == nullptr)57 return false;58 59 DWORD code = 0;60 if (!::GetExitCodeProcess(m_process, &code))61 return false;62 63 return (code == STILL_ACTIVE);64}65 66static lldb::thread_result_t67MonitorThread(const Host::MonitorChildProcessCallback &callback,68 HANDLE process_handle) {69 DWORD exit_code;70 71 ::WaitForSingleObject(process_handle, INFINITE);72 ::GetExitCodeProcess(process_handle, &exit_code);73 callback(::GetProcessId(process_handle), 0, exit_code);74 ::CloseHandle(process_handle);75 return {};76}77 78llvm::Expected<HostThread> HostProcessWindows::StartMonitoring(79 const Host::MonitorChildProcessCallback &callback) {80 HANDLE process_handle;81 82 // Since the life of this HostProcessWindows instance and the life of the83 // process may be different, duplicate the handle so that the monitor thread84 // can have ownership over its own copy of the handle.85 if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(),86 &process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {87 return ThreadLauncher::LaunchThread(88 "ChildProcessMonitor", [callback, process_handle] {89 return MonitorThread(callback, process_handle);90 });91 } else {92 return llvm::errorCodeToError(llvm::mapWindowsError(GetLastError()));93 }94}95 96void HostProcessWindows::Close() {97 if (m_owns_handle && m_process != LLDB_INVALID_PROCESS)98 ::CloseHandle(m_process);99 m_process = nullptr;100}101