1 //===-- PipeWindows.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/windows/PipeWindows.h" 11 12 #include "llvm/Support/raw_ostream.h" 13 14 #include <fcntl.h> 15 #include <io.h> 16 17 #include <atomic> 18 #include <string> 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 namespace 24 { 25 std::atomic<uint32_t> g_pipe_serial(0); 26 } 27 28 PipeWindows::PipeWindows() 29 { 30 m_read = INVALID_HANDLE_VALUE; 31 m_write = INVALID_HANDLE_VALUE; 32 33 m_read_fd = -1; 34 m_write_fd = -1; 35 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 36 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 37 } 38 39 PipeWindows::~PipeWindows() 40 { 41 Close(); 42 } 43 44 Error 45 PipeWindows::CreateNew(bool child_process_inherit) 46 { 47 // Even for anonymous pipes, we open a named pipe. This is because you cannot get 48 // overlapped i/o on Windows without using a named pipe. So we synthesize a unique 49 // name. 50 uint32_t serial = g_pipe_serial.fetch_add(1); 51 std::string pipe_name; 52 llvm::raw_string_ostream pipe_name_stream(pipe_name); 53 pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial; 54 pipe_name_stream.flush(); 55 56 return CreateNew(pipe_name.c_str(), child_process_inherit); 57 } 58 59 Error 60 PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) 61 { 62 if (name.empty()) 63 return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); 64 65 if (CanRead() || CanWrite()) 66 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); 67 68 std::string pipe_path = "\\\\.\\Pipe\\"; 69 pipe_path.append(name); 70 71 // Always open for overlapped i/o. We implement blocking manually in Read and Write. 72 DWORD read_mode = FILE_FLAG_OVERLAPPED; 73 m_read = 74 ::CreateNamedPipe(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL); 75 if (INVALID_HANDLE_VALUE == m_read) 76 return Error(::GetLastError(), eErrorTypeWin32); 77 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); 78 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 79 m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 80 81 // Open the write end of the pipe. 82 Error result = OpenNamedPipe(name, child_process_inherit, false); 83 if (!result.Success()) 84 { 85 CloseReadEndpoint(); 86 return result; 87 } 88 89 return result; 90 } 91 92 Error 93 PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit) 94 { 95 if (CanRead() || CanWrite()) 96 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); 97 98 return OpenNamedPipe(name, child_process_inherit, true); 99 } 100 101 Error 102 PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) 103 { 104 if (CanRead() || CanWrite()) 105 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); 106 107 return OpenNamedPipe(name, child_process_inherit, false); 108 } 109 110 Error 111 PipeWindows::OpenNamedPipe(llvm::StringRef name, bool child_process_inherit, bool is_read) 112 { 113 if (name.empty()) 114 return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32); 115 116 assert(is_read ? !CanRead() : !CanWrite()); 117 118 SECURITY_ATTRIBUTES attributes = {0}; 119 attributes.bInheritHandle = child_process_inherit; 120 121 std::string pipe_path = "\\\\.\\Pipe\\"; 122 pipe_path.append(name); 123 124 if (is_read) 125 { 126 m_read = ::CreateFile(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 127 if (INVALID_HANDLE_VALUE == m_read) 128 return Error(::GetLastError(), eErrorTypeWin32); 129 130 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); 131 132 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 133 m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 134 } 135 else 136 { 137 m_write = ::CreateFile(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 138 if (INVALID_HANDLE_VALUE == m_write) 139 return Error(::GetLastError(), eErrorTypeWin32); 140 141 m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); 142 143 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 144 } 145 146 return Error(); 147 } 148 149 int 150 PipeWindows::GetReadFileDescriptor() const 151 { 152 return m_read_fd; 153 } 154 155 int 156 PipeWindows::GetWriteFileDescriptor() const 157 { 158 return m_write_fd; 159 } 160 161 int 162 PipeWindows::ReleaseReadFileDescriptor() 163 { 164 if (!CanRead()) 165 return -1; 166 int result = m_read_fd; 167 m_read_fd = -1; 168 if (m_read_overlapped.hEvent) 169 ::CloseHandle(m_read_overlapped.hEvent); 170 m_read = INVALID_HANDLE_VALUE; 171 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 172 return result; 173 } 174 175 int 176 PipeWindows::ReleaseWriteFileDescriptor() 177 { 178 if (!CanWrite()) 179 return -1; 180 int result = m_write_fd; 181 m_write_fd = -1; 182 m_write = INVALID_HANDLE_VALUE; 183 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 184 return result; 185 } 186 187 void 188 PipeWindows::CloseReadEndpoint() 189 { 190 if (!CanRead()) 191 return; 192 193 if (m_read_overlapped.hEvent) 194 ::CloseHandle(m_read_overlapped.hEvent); 195 _close(m_read_fd); 196 m_read = INVALID_HANDLE_VALUE; 197 m_read_fd = -1; 198 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 199 } 200 201 void 202 PipeWindows::CloseWriteEndpoint() 203 { 204 if (!CanWrite()) 205 return; 206 207 _close(m_write_fd); 208 m_write = INVALID_HANDLE_VALUE; 209 m_write_fd = -1; 210 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 211 } 212 213 void 214 PipeWindows::Close() 215 { 216 CloseReadEndpoint(); 217 CloseWriteEndpoint(); 218 } 219 220 Error 221 PipeWindows::Delete(llvm::StringRef name) 222 { 223 return Error(); 224 } 225 226 bool 227 PipeWindows::CanRead() const 228 { 229 return (m_read != INVALID_HANDLE_VALUE); 230 } 231 232 bool 233 PipeWindows::CanWrite() const 234 { 235 return (m_write != INVALID_HANDLE_VALUE); 236 } 237 238 HANDLE 239 PipeWindows::GetReadNativeHandle() 240 { 241 return m_read; 242 } 243 244 HANDLE 245 PipeWindows::GetWriteNativeHandle() 246 { 247 return m_write; 248 } 249 250 Error 251 PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read) 252 { 253 if (!CanRead()) 254 return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); 255 256 bytes_read = 0; 257 DWORD sys_bytes_read = size; 258 BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, &m_read_overlapped); 259 if (!result && GetLastError() != ERROR_IO_PENDING) 260 return Error(::GetLastError(), eErrorTypeWin32); 261 262 DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000; 263 DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); 264 if (wait_result != WAIT_OBJECT_0) 265 { 266 // The operation probably failed. However, if it timed out, we need to cancel the I/O. 267 // Between the time we returned from WaitForSingleObject and the time we call CancelIoEx, 268 // the operation may complete. If that hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. 269 // If that happens, the original operation should be considered to have been successful. 270 bool failed = true; 271 DWORD failure_error = ::GetLastError(); 272 if (wait_result == WAIT_TIMEOUT) 273 { 274 BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped); 275 if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) 276 failed = false; 277 } 278 if (failed) 279 return Error(failure_error, eErrorTypeWin32); 280 } 281 282 // Now we call GetOverlappedResult setting bWait to false, since we've already waited 283 // as long as we're willing to. 284 if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) 285 return Error(::GetLastError(), eErrorTypeWin32); 286 287 bytes_read = sys_bytes_read; 288 return Error(); 289 } 290 291 Error 292 PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written) 293 { 294 if (!CanWrite()) 295 return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); 296 297 DWORD sys_bytes_written = 0; 298 BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, &m_write_overlapped); 299 if (!write_result && GetLastError() != ERROR_IO_PENDING) 300 return Error(::GetLastError(), eErrorTypeWin32); 301 302 BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, TRUE); 303 if (!result) 304 return Error(::GetLastError(), eErrorTypeWin32); 305 return Error(); 306 } 307