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_private; 21 22 namespace 23 { 24 std::atomic<uint32_t> g_pipe_serial(0); 25 } 26 27 Pipe::Pipe() 28 { 29 m_read = INVALID_HANDLE_VALUE; 30 m_write = INVALID_HANDLE_VALUE; 31 32 m_read_fd = -1; 33 m_write_fd = -1; 34 35 m_read_overlapped = nullptr; 36 m_write_overlapped = nullptr; 37 } 38 39 Pipe::~Pipe() 40 { 41 Close(); 42 } 43 44 bool 45 Pipe::Open(bool read_overlapped, bool write_overlapped) 46 { 47 if (IsValid()) 48 return true; 49 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 << "\\\\.\\Pipe\\lldb.pipe." << ::GetCurrentProcessId() << "." << serial; 54 pipe_name_stream.flush(); 55 56 DWORD read_mode = 0; 57 DWORD write_mode = 0; 58 if (read_overlapped) 59 read_mode |= FILE_FLAG_OVERLAPPED; 60 if (write_overlapped) 61 write_mode |= FILE_FLAG_OVERLAPPED; 62 m_read = 63 ::CreateNamedPipe(pipe_name.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL); 64 if (INVALID_HANDLE_VALUE == m_read) 65 return false; 66 m_write = ::CreateFile(pipe_name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, write_mode, NULL); 67 if (INVALID_HANDLE_VALUE == m_write) 68 { 69 ::CloseHandle(m_read); 70 m_read = INVALID_HANDLE_VALUE; 71 return false; 72 } 73 74 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY); 75 m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY); 76 77 if (read_overlapped) 78 { 79 m_read_overlapped = new OVERLAPPED; 80 ZeroMemory(m_read_overlapped, sizeof(OVERLAPPED)); 81 } 82 if (write_overlapped) 83 { 84 m_write_overlapped = new OVERLAPPED; 85 ZeroMemory(m_write_overlapped, sizeof(OVERLAPPED)); 86 } 87 return true; 88 } 89 90 int 91 Pipe::GetReadFileDescriptor() const 92 { 93 return m_read_fd; 94 } 95 96 int 97 Pipe::GetWriteFileDescriptor() const 98 { 99 return m_write_fd; 100 } 101 102 int 103 Pipe::ReleaseReadFileDescriptor() 104 { 105 int result = m_read_fd; 106 m_read_fd = -1; 107 m_read = INVALID_HANDLE_VALUE; 108 if (m_read_overlapped) 109 { 110 delete m_read_overlapped; 111 m_read_overlapped = nullptr; 112 } 113 return result; 114 } 115 116 int 117 Pipe::ReleaseWriteFileDescriptor() 118 { 119 int result = m_write_fd; 120 m_write_fd = -1; 121 m_write = INVALID_HANDLE_VALUE; 122 if (m_write_overlapped) 123 { 124 delete m_write_overlapped; 125 m_write_overlapped = nullptr; 126 } 127 return result; 128 } 129 130 void 131 Pipe::Close() 132 { 133 CloseReadFileDescriptor(); 134 CloseWriteFileDescriptor(); 135 } 136 137 bool 138 Pipe::ReadDescriptorIsValid() const 139 { 140 return m_read_fd != -1; 141 } 142 143 bool 144 Pipe::WriteDescriptorIsValid() const 145 { 146 return m_write_fd != -1; 147 } 148 149 bool 150 Pipe::IsValid() const 151 { 152 return ReadDescriptorIsValid() && WriteDescriptorIsValid(); 153 } 154 155 bool 156 Pipe::CloseReadFileDescriptor() 157 { 158 if (ReadDescriptorIsValid()) 159 { 160 int err; 161 err = _close(m_read_fd); 162 m_read_fd = -1; 163 m_read = INVALID_HANDLE_VALUE; 164 if (m_read_overlapped) 165 { 166 delete m_read_overlapped; 167 m_read_overlapped = nullptr; 168 } 169 return err == 0; 170 } 171 return true; 172 } 173 174 bool 175 Pipe::CloseWriteFileDescriptor() 176 { 177 if (WriteDescriptorIsValid()) 178 { 179 int err; 180 err = _close(m_write_fd); 181 m_write_fd = -1; 182 m_write = INVALID_HANDLE_VALUE; 183 if (m_write_overlapped) 184 { 185 delete m_write_overlapped; 186 m_write_overlapped = nullptr; 187 } 188 return err == 0; 189 } 190 return true; 191 } 192 193 HANDLE 194 Pipe::GetReadNativeHandle() 195 { 196 return m_read; 197 } 198 199 HANDLE 200 Pipe::GetWriteNativeHandle() 201 { 202 return m_write; 203 } 204 205 size_t 206 Pipe::Read(void *buf, size_t num_bytes) 207 { 208 if (ReadDescriptorIsValid()) 209 { 210 DWORD bytes_read = 0; 211 ::ReadFile(m_read, buf, num_bytes, &bytes_read, m_read_overlapped); 212 if (m_read_overlapped) 213 GetOverlappedResult(m_read, m_read_overlapped, &bytes_read, TRUE); 214 return bytes_read; 215 } 216 return 0; // Return 0 since errno won't be set if we didn't call read 217 } 218 219 size_t 220 Pipe::Write(const void *buf, size_t num_bytes) 221 { 222 if (WriteDescriptorIsValid()) 223 { 224 DWORD bytes_written = 0; 225 ::WriteFile(m_write, buf, num_bytes, &bytes_written, m_read_overlapped); 226 if (m_write_overlapped) 227 GetOverlappedResult(m_write, m_write_overlapped, &bytes_written, TRUE); 228 return bytes_written; 229 } 230 return 0; // Return 0 since errno won't be set if we didn't call write 231 } 232