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 = ::CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 77 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 CloseReadFileDescriptor(); 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 = 157 ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 158 if (INVALID_HANDLE_VALUE == m_read) 159 return Error(::GetLastError(), eErrorTypeWin32); 160 161 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); 162 163 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 164 m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 165 } 166 else 167 { 168 m_write = 169 ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 170 if (INVALID_HANDLE_VALUE == m_write) 171 return Error(::GetLastError(), eErrorTypeWin32); 172 173 m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); 174 175 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 176 } 177 178 return Error(); 179 } 180 181 int 182 PipeWindows::GetReadFileDescriptor() const 183 { 184 return m_read_fd; 185 } 186 187 int 188 PipeWindows::GetWriteFileDescriptor() const 189 { 190 return m_write_fd; 191 } 192 193 int 194 PipeWindows::ReleaseReadFileDescriptor() 195 { 196 if (!CanRead()) 197 return -1; 198 int result = m_read_fd; 199 m_read_fd = -1; 200 if (m_read_overlapped.hEvent) 201 ::CloseHandle(m_read_overlapped.hEvent); 202 m_read = INVALID_HANDLE_VALUE; 203 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 204 return result; 205 } 206 207 int 208 PipeWindows::ReleaseWriteFileDescriptor() 209 { 210 if (!CanWrite()) 211 return -1; 212 int result = m_write_fd; 213 m_write_fd = -1; 214 m_write = INVALID_HANDLE_VALUE; 215 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 216 return result; 217 } 218 219 void 220 PipeWindows::CloseReadFileDescriptor() 221 { 222 if (!CanRead()) 223 return; 224 225 if (m_read_overlapped.hEvent) 226 ::CloseHandle(m_read_overlapped.hEvent); 227 _close(m_read_fd); 228 m_read = INVALID_HANDLE_VALUE; 229 m_read_fd = -1; 230 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped)); 231 } 232 233 void 234 PipeWindows::CloseWriteFileDescriptor() 235 { 236 if (!CanWrite()) 237 return; 238 239 _close(m_write_fd); 240 m_write = INVALID_HANDLE_VALUE; 241 m_write_fd = -1; 242 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped)); 243 } 244 245 void 246 PipeWindows::Close() 247 { 248 CloseReadFileDescriptor(); 249 CloseWriteFileDescriptor(); 250 } 251 252 Error 253 PipeWindows::Delete(llvm::StringRef name) 254 { 255 return Error(); 256 } 257 258 bool 259 PipeWindows::CanRead() const 260 { 261 return (m_read != INVALID_HANDLE_VALUE); 262 } 263 264 bool 265 PipeWindows::CanWrite() const 266 { 267 return (m_write != INVALID_HANDLE_VALUE); 268 } 269 270 HANDLE 271 PipeWindows::GetReadNativeHandle() 272 { 273 return m_read; 274 } 275 276 HANDLE 277 PipeWindows::GetWriteNativeHandle() 278 { 279 return m_write; 280 } 281 282 Error 283 PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read) 284 { 285 if (!CanRead()) 286 return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); 287 288 bytes_read = 0; 289 DWORD sys_bytes_read = size; 290 BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, &m_read_overlapped); 291 if (!result && GetLastError() != ERROR_IO_PENDING) 292 return Error(::GetLastError(), eErrorTypeWin32); 293 294 DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000; 295 DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); 296 if (wait_result != WAIT_OBJECT_0) 297 { 298 // The operation probably failed. However, if it timed out, we need to cancel the I/O. 299 // Between the time we returned from WaitForSingleObject and the time we call CancelIoEx, 300 // the operation may complete. If that hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. 301 // If that happens, the original operation should be considered to have been successful. 302 bool failed = true; 303 DWORD failure_error = ::GetLastError(); 304 if (wait_result == WAIT_TIMEOUT) 305 { 306 BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped); 307 if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) 308 failed = false; 309 } 310 if (failed) 311 return Error(failure_error, eErrorTypeWin32); 312 } 313 314 // Now we call GetOverlappedResult setting bWait to false, since we've already waited 315 // as long as we're willing to. 316 if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE)) 317 return Error(::GetLastError(), eErrorTypeWin32); 318 319 bytes_read = sys_bytes_read; 320 return Error(); 321 } 322 323 Error 324 PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written) 325 { 326 if (!CanWrite()) 327 return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); 328 329 DWORD sys_bytes_written = 0; 330 BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, &m_write_overlapped); 331 if (!write_result && GetLastError() != ERROR_IO_PENDING) 332 return Error(::GetLastError(), eErrorTypeWin32); 333 334 BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, TRUE); 335 if (!result) 336 return Error(::GetLastError(), eErrorTypeWin32); 337 return Error(); 338 } 339