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