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 HostProcess::MonitorCallback callback; 28 void *baton; 29 HANDLE process_handle; 30 }; 31 } 32 33 HostProcessWindows::HostProcessWindows() 34 : HostNativeProcessBase() 35 , m_owns_handle(true) 36 { 37 } 38 39 HostProcessWindows::HostProcessWindows(lldb::process_t process) 40 : HostNativeProcessBase(process) 41 , m_owns_handle(true) 42 { 43 } 44 45 HostProcessWindows::~HostProcessWindows() 46 { 47 Close(); 48 } 49 50 void 51 HostProcessWindows::SetOwnsHandle(bool owns) 52 { 53 m_owns_handle = owns; 54 } 55 56 Error HostProcessWindows::Terminate() 57 { 58 Error error; 59 if (m_process == nullptr) 60 error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); 61 62 if (!::TerminateProcess(m_process, 0)) 63 error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 64 65 return error; 66 } 67 68 Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const 69 { 70 Error error; 71 if (m_process == nullptr) 72 error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); 73 74 std::vector<wchar_t> wpath(PATH_MAX); 75 if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) 76 { 77 std::string path; 78 if (llvm::convertWideToUTF8(wpath.data(), path)) 79 file_spec.SetFile(path, false); 80 else 81 error.SetErrorString("Error converting path to UTF-8"); 82 } 83 else 84 error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 85 86 return error; 87 } 88 89 lldb::pid_t HostProcessWindows::GetProcessId() const 90 { 91 return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); 92 } 93 94 bool HostProcessWindows::IsRunning() const 95 { 96 if (m_process == nullptr) 97 return false; 98 99 DWORD code = 0; 100 if (!::GetExitCodeProcess(m_process, &code)) 101 return false; 102 103 return (code == STILL_ACTIVE); 104 } 105 106 HostThread 107 HostProcessWindows::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) 108 { 109 HostThread monitor_thread; 110 MonitorInfo *info = new MonitorInfo; 111 info->callback = callback; 112 info->baton = callback_baton; 113 114 // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that 115 // the monitor thread can have ownership over its own copy of the handle. 116 HostThread result; 117 if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) 118 result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr); 119 return result; 120 } 121 122 lldb::thread_result_t 123 HostProcessWindows::MonitorThread(void *thread_arg) 124 { 125 DWORD exit_code; 126 127 MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); 128 if (info) 129 { 130 ::WaitForSingleObject(info->process_handle, INFINITE); 131 ::GetExitCodeProcess(info->process_handle, &exit_code); 132 info->callback(info->baton, ::GetProcessId(info->process_handle), true, 0, exit_code); 133 ::CloseHandle(info->process_handle); 134 delete (info); 135 } 136 return 0; 137 } 138 139 void HostProcessWindows::Close() 140 { 141 if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) 142 ::CloseHandle(m_process); 143 m_process = nullptr; 144 } 145