blob: 852630eb04bc5db468a9b54de5e2d53d8a653710 [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
12#include "llvm/Support/raw_ostream.h"
13
14#include <fcntl.h>
15#include <io.h>
16
17#include <atomic>
18#include <string>
19
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000020using namespace lldb;
Zachary Turnerb2df30d2014-10-08 20:38:41 +000021using namespace lldb_private;
22
23namespace
24{
25std::atomic<uint32_t> g_pipe_serial(0);
26}
27
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000028PipeWindows::PipeWindows()
Zachary Turnerb2df30d2014-10-08 20:38:41 +000029{
30 m_read = INVALID_HANDLE_VALUE;
31 m_write = INVALID_HANDLE_VALUE;
32
33 m_read_fd = -1;
34 m_write_fd = -1;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000035 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
36 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
Zachary Turnerb2df30d2014-10-08 20:38:41 +000037}
38
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000039PipeWindows::~PipeWindows()
Zachary Turnerb2df30d2014-10-08 20:38:41 +000040{
41 Close();
42}
43
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000044Error
45PipeWindows::CreateNew(bool child_process_inherit)
Zachary Turnerb2df30d2014-10-08 20:38:41 +000046{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000047 // 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.
Zachary Turnerb2df30d2014-10-08 20:38:41 +000050 uint32_t serial = g_pipe_serial.fetch_add(1);
51 std::string pipe_name;
52 llvm::raw_string_ostream pipe_name_stream(pipe_name);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000053 pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial;
Zachary Turnerb2df30d2014-10-08 20:38:41 +000054 pipe_name_stream.flush();
55
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000056 return CreateNew(pipe_name.c_str(), child_process_inherit);
57}
58
59Error
60PipeWindows::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;
Zachary Turnerb2df30d2014-10-08 20:38:41 +000073 m_read =
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000074 ::CreateNamedPipe(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
Zachary Turnerb2df30d2014-10-08 20:38:41 +000075 if (INVALID_HANDLE_VALUE == m_read)
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000076 return Error(::GetLastError(), eErrorTypeWin32);
Zachary Turnerb2df30d2014-10-08 20:38:41 +000077 m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000078 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
79 m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
Zachary Turnerb2df30d2014-10-08 20:38:41 +000080
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000081 // Open the write end of the pipe.
82 Error result = OpenNamedPipe(name, child_process_inherit, false);
83 if (!result.Success())
Zachary Turnerb2df30d2014-10-08 20:38:41 +000084 {
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000085 CloseReadEndpoint();
86 return result;
Zachary Turnerb2df30d2014-10-08 20:38:41 +000087 }
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000088
89 return result;
90}
91
92Error
Oleksiy Vyalov47718292015-01-14 01:31:27 +000093PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit)
Zachary Turner0b9d3ee2014-12-17 18:02:19 +000094{
95 if (CanRead() || CanWrite())
96 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
97
98 return OpenNamedPipe(name, child_process_inherit, true);
99}
100
101Error
Oleksiy Vyalovd5f8b6a2015-01-13 23:19:40 +0000102PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000103{
104 if (CanRead() || CanWrite())
105 return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
106
107 return OpenNamedPipe(name, child_process_inherit, false);
108}
109
110Error
111PipeWindows::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)
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000125 {
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000126 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);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000134 }
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000135 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();
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000147}
148
149int
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000150PipeWindows::GetReadFileDescriptor() const
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000151{
152 return m_read_fd;
153}
154
155int
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000156PipeWindows::GetWriteFileDescriptor() const
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000157{
158 return m_write_fd;
159}
160
161int
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000162PipeWindows::ReleaseReadFileDescriptor()
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000163{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000164 if (!CanRead())
165 return -1;
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000166 int result = m_read_fd;
167 m_read_fd = -1;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000168 if (m_read_overlapped.hEvent)
169 ::CloseHandle(m_read_overlapped.hEvent);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000170 m_read = INVALID_HANDLE_VALUE;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000171 ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000172 return result;
173}
174
175int
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000176PipeWindows::ReleaseWriteFileDescriptor()
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000177{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000178 if (!CanWrite())
179 return -1;
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000180 int result = m_write_fd;
181 m_write_fd = -1;
182 m_write = INVALID_HANDLE_VALUE;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000183 ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000184 return result;
185}
186
187void
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000188PipeWindows::CloseReadEndpoint()
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000189{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000190 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
201void
202PipeWindows::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
213void
214PipeWindows::Close()
215{
216 CloseReadEndpoint();
217 CloseWriteEndpoint();
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000218}
219
Oleksiy Vyalovd5f8b6a2015-01-13 23:19:40 +0000220Error
221PipeWindows::Delete(llvm::StringRef name)
222{
223 return Error();
224}
225
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000226bool
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000227PipeWindows::CanRead() const
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000228{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000229 return (m_read != INVALID_HANDLE_VALUE);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000230}
231
232bool
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000233PipeWindows::CanWrite() const
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000234{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000235 return (m_write != INVALID_HANDLE_VALUE);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000236}
237
238HANDLE
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000239PipeWindows::GetReadNativeHandle()
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000240{
241 return m_read;
242}
243
244HANDLE
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000245PipeWindows::GetWriteNativeHandle()
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000246{
247 return m_write;
248}
249
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000250Error
Oleksiy Vyalovd5f8b6a2015-01-13 23:19:40 +0000251PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read)
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000252{
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000253 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
Oleksiy Vyalovd5f8b6a2015-01-13 23:19:40 +0000262 DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000;
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000263 DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout);
264 if (wait_result != WAIT_OBJECT_0)
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000265 {
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000266 // 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);
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000280 }
Zachary Turner0b9d3ee2014-12-17 18:02:19 +0000281
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
291Error
292PipeWindows::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();
Zachary Turnerb2df30d2014-10-08 20:38:41 +0000306}