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 18 #include <Psapi.h> 19 20 using namespace lldb_private; 21 22 namespace 23 { 24 struct MonitorInfo 25 { 26 HostProcess::MonitorCallback callback; 27 void *baton; 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 char path[MAX_PATH] = { 0 }; 74 if (::GetProcessImageFileName(m_process, path, llvm::array_lengthof(path))) 75 file_spec.SetFile(path, false); 76 else 77 error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 78 79 return error; 80 } 81 82 lldb::pid_t HostProcessWindows::GetProcessId() const 83 { 84 return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process); 85 } 86 87 bool HostProcessWindows::IsRunning() const 88 { 89 if (m_process == nullptr) 90 return false; 91 92 DWORD code = 0; 93 if (!::GetExitCodeProcess(m_process, &code)) 94 return false; 95 96 return (code == STILL_ACTIVE); 97 } 98 99 HostThread 100 HostProcessWindows::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) 101 { 102 HostThread monitor_thread; 103 MonitorInfo *info = new MonitorInfo; 104 info->callback = callback; 105 info->baton = callback_baton; 106 107 // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that 108 // the monitor thread can have ownership over its own copy of the handle. 109 HostThread result; 110 if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) 111 result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr); 112 return result; 113 } 114 115 lldb::thread_result_t 116 HostProcessWindows::MonitorThread(void *thread_arg) 117 { 118 DWORD exit_code; 119 120 MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg); 121 if (info) 122 { 123 ::WaitForSingleObject(info->process_handle, INFINITE); 124 ::GetExitCodeProcess(info->process_handle, &exit_code); 125 info->callback(info->baton, ::GetProcessId(info->process_handle), true, 0, exit_code); 126 ::CloseHandle(info->process_handle); 127 delete (info); 128 } 129 return 0; 130 } 131 132 void HostProcessWindows::Close() 133 { 134 if (m_owns_handle && m_process != LLDB_INVALID_PROCESS) 135 ::CloseHandle(m_process); 136 m_process = nullptr; 137 } 138