blob: 572be8784091910953a43eecbeabe1864bae5311 [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
20using namespace lldb_private;
21
22namespace
23{
24std::atomic<uint32_t> g_pipe_serial(0);
25}
26
27Pipe::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
39Pipe::~Pipe()
40{
41 Close();
42}
43
44bool
45Pipe::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
90int
91Pipe::GetReadFileDescriptor() const
92{
93 return m_read_fd;
94}
95
96int
97Pipe::GetWriteFileDescriptor() const
98{
99 return m_write_fd;
100}
101
102int
103Pipe::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
116int
117Pipe::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
130void
131Pipe::Close()
132{
133 CloseReadFileDescriptor();
134 CloseWriteFileDescriptor();
135}
136
137bool
138Pipe::ReadDescriptorIsValid() const
139{
140 return m_read_fd != -1;
141}
142
143bool
144Pipe::WriteDescriptorIsValid() const
145{
146 return m_write_fd != -1;
147}
148
149bool
150Pipe::IsValid() const
151{
152 return ReadDescriptorIsValid() && WriteDescriptorIsValid();
153}
154
155bool
156Pipe::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
174bool
175Pipe::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
193HANDLE
194Pipe::GetReadNativeHandle()
195{
196 return m_read;
197}
198
199HANDLE
200Pipe::GetWriteNativeHandle()
201{
202 return m_write;
203}
204
205size_t
206Pipe::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
219size_t
220Pipe::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}