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