1 //===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Host/FileSpec.h" 11 #include "lldb/Host/HostThread.h" 12 #include "lldb/Host/ThreadLauncher.h" 13 #include "lldb/Host/windows/windows.h" 14 #include "lldb/Host/windows/HostProcessWindows.h" 15 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/Support/ConvertUTF.h" 18 19 #include <Psapi.h> 20 21 using namespace lldb_private; 22 23 namespace 24 { 25 struct MonitorInfo 26 { 27 Host::MonitorChildProcessCallback callback; 28 HANDLE process_handle; 29 }; 30 } 31 32 HostProcessWindows::HostProcessWindows() 33 : HostNativeProcessBase() 34 , m_owns_handle(true) 35 { 36 } 37 38 HostProcessWindows::HostProcessWindows(lldb::process_t process) 39 : HostNativeProcessBase(process) 40 , m_owns_handle(true) 41 { 42 } 43 44 HostProcessWindows::~HostProcessWindows() 45 { 46 Close(); 47 } 48 49 void 50 HostProcessWindows::SetOwnsHandle(bool owns) 51 { 52 m_owns_handle = owns; 53 } 54 55 Error HostProcessWindows::Terminate() 56 { 57 Error error; 58 if (m_process == nullptr) 59 error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); 60 61 if (!::TerminateProcess(m_process, 0)) 62 error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 63 64 return error; 65 } 66 67 Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const 68 { 69 Error error; 70 if (m_process == nullptr) 71 error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); 72 73 std::vector<wchar_t> wpath(PATH_MAX); 74 if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) 75 { 76 std::string path; 77 if (llvm::convertWideToUTF8(wpath.data(), path)) 78 file_spec.SetFile(path, false); 79 else 80 error.SetErrorString("Error converting path to UTF-8"); 81 } 82 else 83 error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 84 85 return error; 86 } 87 88 lldb::pid_t HostProcessWindows::GetProcessId() const 89 { 90 return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); 91 } 92 93 bool HostProcessWindows::IsRunning() const 94 { 95 if (m_process == nullptr) 96 return false; 97 98 DWORD code = 0; 99 if (!::GetExitCodeProcess(m_process, &code)) 100 return false; 101 102 return (code == STILL_ACTIVE); 103 } 104 105 HostThread 106 HostProcessWindows::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) 107 { 108 HostThread monitor_thread; 109 MonitorInfo *info = new MonitorInfo; 110 info->callback = callback; 111 112 // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that 113 // the monitor thread can have ownership over its own copy of the handle. 114 HostThread result; 115 if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) 116 result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr); 117 return result; 118 } 119 120 lldb::thread_result_t 121 HostProcessWindows::MonitorThread(void *thread_arg) 122 { 123 DWORD exit_code; 124 125 MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); 126 if (info) 127 { 128 ::WaitForSingleObject(info->process_handle, INFINITE); 129 ::GetExitCodeProcess(info->process_handle, &exit_code); 130 info->callback(::GetProcessId(info->process_handle), true, 0, exit_code); 131 ::CloseHandle(info->process_handle); 132 delete (info); 133 } 134 return 0; 135 } 136 137 void HostProcessWindows::Close() 138 { 139 if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) 140 ::CloseHandle(m_process); 141 m_process = nullptr; 142 } 143