blob: 407f0468e6cb04f7feb0f4f6ad2a2aae319b7cc0 [file] [log] [blame]
Zachary Turnerb2df30d2014-10-08 20:38:41 +00001//===-- 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
Oleksiy Vyalov4536c452015-02-05 16:29:12 +000012#include "llvm/ADT/SmallString.h"
13#include "llvm/Support/Process.h"
Zachary Turnerb2df30d2014-10-08 20:38:41 +000014#include "llvm/Support/raw_ostream.h"
15
16#include <fcntl.h>
17#include <io.h>
Zachary Turneraa60e3c2015-02-11 18:21:28 +000018#include <rpc.h>
Zachary Turnerb2df30d2014-10-08 20:38:41 +000019
20#include <atomic>
21#include <string>
22
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000023using namespace lldb;
Zachary Turnerb2df30d2014-10-08 20:38:41 +000024using namespace lldb_private;
25
Kate Stoneb9c1b512016-09-06 20:57:50 +000026namespace {
Zachary Turnerb2df30d2014-10-08 20:38:41 +000027std::atomic<uint32_t> g_pipe_serial(0);
28}
29
Kate Stoneb9c1b512016-09-06 20:57:50 +000030PipeWindows::PipeWindows() {
31 m_read = INVALID_HANDLE_VALUE;
32 m_write = INVALID_HANDLE_VALUE;
Zachary Turnerb2df30d2014-10-08 20:38:41 +000033
Kate Stoneb9c1b512016-09-06 20:57:50 +000034 m_read_fd = -1;
35 m_write_fd = -1;
36 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
37 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
Zachary Turnerb2df30d2014-10-08 20:38:41 +000038}
39
Kate Stoneb9c1b512016-09-06 20:57:50 +000040PipeWindows::~PipeWindows() { Close(); }
41
42Error PipeWindows::CreateNew(bool child_process_inherit) {
43 // Even for anonymous pipes, we open a named pipe. This is because you cannot
44 // get
45 // overlapped i/o on Windows without using a named pipe. So we synthesize a
46 // unique
47 // name.
48 uint32_t serial = g_pipe_serial.fetch_add(1);
49 std::string pipe_name;
50 llvm::raw_string_ostream pipe_name_stream(pipe_name);
51 pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial;
52 pipe_name_stream.flush();
53
54 return CreateNew(pipe_name.c_str(), child_process_inherit);
Zachary Turnerb2df30d2014-10-08 20:38:41 +000055}
56
Kate Stoneb9c1b512016-09-06 20:57:50 +000057Error PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) {
58 if (name.empty())
59 return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32);
Zachary Turnerb2df30d2014-10-08 20:38:41 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 if (CanRead() || CanWrite())
62 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
63
64 std::string pipe_path = "\\\\.\\Pipe\\";
65 pipe_path.append(name);
66
67 // Always open for overlapped i/o. We implement blocking manually in Read and
68 // Write.
69 DWORD read_mode = FILE_FLAG_OVERLAPPED;
70 m_read = ::CreateNamedPipeA(
71 pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode,
72 PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
73 if (INVALID_HANDLE_VALUE == m_read)
74 return Error(::GetLastError(), eErrorTypeWin32);
75 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
76 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
77 m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
78
79 // Open the write end of the pipe.
80 Error result = OpenNamedPipe(name, child_process_inherit, false);
81 if (!result.Success()) {
82 CloseReadFileDescriptor();
83 return result;
84 }
85
86 return result;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000087}
88
Kate Stoneb9c1b512016-09-06 20:57:50 +000089Error PipeWindows::CreateWithUniqueName(llvm::StringRef prefix,
90 bool child_process_inherit,
91 llvm::SmallVectorImpl<char> &name) {
92 llvm::SmallString<128> pipe_name;
93 Error error;
94 ::UUID unique_id;
95 RPC_CSTR unique_string;
96 RPC_STATUS status = ::UuidCreate(&unique_id);
97 if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY)
98 status = ::UuidToStringA(&unique_id, &unique_string);
99 if (status == RPC_S_OK) {
100 pipe_name = prefix;
101 pipe_name += "-";
102 pipe_name += reinterpret_cast<char *>(unique_string);
103 ::RpcStringFreeA(&unique_string);
104 error = CreateNew(pipe_name, child_process_inherit);
105 } else {
106 error.SetError(status, eErrorTypeWin32);
107 }
108 if (error.Success())
109 name = pipe_name;
110 return error;
111}
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000112
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113Error PipeWindows::OpenAsReader(llvm::StringRef name,
114 bool child_process_inherit) {
115 if (CanRead() || CanWrite())
116 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000117
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118 return OpenNamedPipe(name, child_process_inherit, true);
119}
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121Error PipeWindows::OpenAsWriterWithTimeout(
122 llvm::StringRef name, bool child_process_inherit,
123 const std::chrono::microseconds &timeout) {
124 if (CanRead() || CanWrite())
125 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
126
127 return OpenNamedPipe(name, child_process_inherit, false);
128}
129
130Error PipeWindows::OpenNamedPipe(llvm::StringRef name,
131 bool child_process_inherit, bool is_read) {
132 if (name.empty())
133 return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32);
134
135 assert(is_read ? !CanRead() : !CanWrite());
136
Zachary Turner5a8ad4592016-10-05 17:07:34 +0000137 SECURITY_ATTRIBUTES attributes = {};
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 attributes.bInheritHandle = child_process_inherit;
139
140 std::string pipe_path = "\\\\.\\Pipe\\";
141 pipe_path.append(name);
142
143 if (is_read) {
144 m_read = ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes,
145 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000146 if (INVALID_HANDLE_VALUE == m_read)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 return Error(::GetLastError(), eErrorTypeWin32);
148
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000149 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000151 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
152 m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153 } else {
154 m_write = ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes,
155 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
156 if (INVALID_HANDLE_VALUE == m_write)
157 return Error(::GetLastError(), eErrorTypeWin32);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000158
Kate Stoneb9c1b512016-09-06 20:57:50 +0000159 m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000160
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000161 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162 }
163
Mehdi Amini665be502016-11-11 05:07:57 +0000164 return Error();
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000165}
166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167int PipeWindows::GetReadFileDescriptor() const { return m_read_fd; }
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000168
Kate Stoneb9c1b512016-09-06 20:57:50 +0000169int PipeWindows::GetWriteFileDescriptor() const { return m_write_fd; }
170
171int PipeWindows::ReleaseReadFileDescriptor() {
172 if (!CanRead())
173 return -1;
174 int result = m_read_fd;
175 m_read_fd = -1;
176 if (m_read_overlapped.hEvent)
177 ::CloseHandle(m_read_overlapped.hEvent);
178 m_read = INVALID_HANDLE_VALUE;
179 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
180 return result;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000181}
182
Kate Stoneb9c1b512016-09-06 20:57:50 +0000183int PipeWindows::ReleaseWriteFileDescriptor() {
184 if (!CanWrite())
185 return -1;
186 int result = m_write_fd;
187 m_write_fd = -1;
188 m_write = INVALID_HANDLE_VALUE;
189 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
190 return result;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000191}
192
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193void PipeWindows::CloseReadFileDescriptor() {
194 if (!CanRead())
195 return;
196
197 if (m_read_overlapped.hEvent)
198 ::CloseHandle(m_read_overlapped.hEvent);
199 _close(m_read_fd);
200 m_read = INVALID_HANDLE_VALUE;
201 m_read_fd = -1;
202 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000203}
204
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205void PipeWindows::CloseWriteFileDescriptor() {
206 if (!CanWrite())
207 return;
208
209 _close(m_write_fd);
210 m_write = INVALID_HANDLE_VALUE;
211 m_write_fd = -1;
212 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
Oleksiy Vyalovd5f8b6a2015-01-13 23:19:40 +0000213}
214
Kate Stoneb9c1b512016-09-06 20:57:50 +0000215void PipeWindows::Close() {
216 CloseReadFileDescriptor();
217 CloseWriteFileDescriptor();
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000218}
219
Mehdi Amini665be502016-11-11 05:07:57 +0000220Error PipeWindows::Delete(llvm::StringRef name) { return Error(); }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000221
222bool PipeWindows::CanRead() const { return (m_read != INVALID_HANDLE_VALUE); }
223
224bool PipeWindows::CanWrite() const { return (m_write != INVALID_HANDLE_VALUE); }
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000225
226HANDLE
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227PipeWindows::GetReadNativeHandle() { return m_read; }
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000228
229HANDLE
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230PipeWindows::GetWriteNativeHandle() { return m_write; }
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232Error PipeWindows::ReadWithTimeout(void *buf, size_t size,
233 const std::chrono::microseconds &duration,
234 size_t &bytes_read) {
235 if (!CanRead())
236 return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000237
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 bytes_read = 0;
239 DWORD sys_bytes_read = size;
240 BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read,
241 &m_read_overlapped);
242 if (!result && GetLastError() != ERROR_IO_PENDING)
243 return Error(::GetLastError(), eErrorTypeWin32);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000244
Kate Stoneb9c1b512016-09-06 20:57:50 +0000245 DWORD timeout = (duration == std::chrono::microseconds::zero())
246 ? INFINITE
247 : duration.count() * 1000;
248 DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout);
249 if (wait_result != WAIT_OBJECT_0) {
250 // The operation probably failed. However, if it timed out, we need to
251 // cancel the I/O.
252 // Between the time we returned from WaitForSingleObject and the time we
253 // call CancelIoEx,
254 // the operation may complete. If that hapens, CancelIoEx will fail and
255 // return ERROR_NOT_FOUND.
256 // If that happens, the original operation should be considered to have been
257 // successful.
258 bool failed = true;
259 DWORD failure_error = ::GetLastError();
260 if (wait_result == WAIT_TIMEOUT) {
261 BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped);
262 if (!cancel_result && GetLastError() == ERROR_NOT_FOUND)
263 failed = false;
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000264 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265 if (failed)
266 return Error(failure_error, eErrorTypeWin32);
267 }
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 // Now we call GetOverlappedResult setting bWait to false, since we've already
270 // waited
271 // as long as we're willing to.
272 if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE))
273 return Error(::GetLastError(), eErrorTypeWin32);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 bytes_read = sys_bytes_read;
Mehdi Amini665be502016-11-11 05:07:57 +0000276 return Error();
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000277}
278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279Error PipeWindows::Write(const void *buf, size_t num_bytes,
280 size_t &bytes_written) {
281 if (!CanWrite())
282 return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000283
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 DWORD sys_bytes_written = 0;
285 BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written,
286 &m_write_overlapped);
287 if (!write_result && GetLastError() != ERROR_IO_PENDING)
288 return Error(::GetLastError(), eErrorTypeWin32);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000289
Kate Stoneb9c1b512016-09-06 20:57:50 +0000290 BOOL result = GetOverlappedResult(m_write, &m_write_overlapped,
291 &sys_bytes_written, TRUE);
292 if (!result)
293 return Error(::GetLastError(), eErrorTypeWin32);
Mehdi Amini665be502016-11-11 05:07:57 +0000294 return Error();
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000295}