@@ -58,30 +58,15 @@ PipeWindows::PipeWindows(pipe_t read, pipe_t write)
58
58
}
59
59
60
60
ZeroMemory (&m_read_overlapped, sizeof (m_read_overlapped));
61
+ m_read_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
62
+
61
63
ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
64
+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
62
65
}
63
66
64
67
PipeWindows::~PipeWindows () { Close (); }
65
68
66
69
Status PipeWindows::CreateNew (bool child_process_inherit) {
67
- // Create an anonymous pipe with the specified inheritance.
68
- SECURITY_ATTRIBUTES sa{sizeof (SECURITY_ATTRIBUTES), 0 ,
69
- child_process_inherit ? TRUE : FALSE };
70
- BOOL result = ::CreatePipe (&m_read, &m_write, &sa, 1024 );
71
- if (result == FALSE )
72
- return Status (::GetLastError (), eErrorTypeWin32);
73
-
74
- m_read_fd = _open_osfhandle ((intptr_t )m_read, _O_RDONLY);
75
- ZeroMemory (&m_read_overlapped, sizeof (m_read_overlapped));
76
- m_read_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
77
-
78
- m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
79
- ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
80
-
81
- return Status ();
82
- }
83
-
84
- Status PipeWindows::CreateNewNamed (bool child_process_inherit) {
85
70
// Even for anonymous pipes, we open a named pipe. This is because you
86
71
// cannot get overlapped i/o on Windows without using a named pipe. So we
87
72
// synthesize a unique name.
@@ -105,12 +90,18 @@ Status PipeWindows::CreateNew(llvm::StringRef name,
105
90
std::string pipe_path = g_pipe_name_prefix.str ();
106
91
pipe_path.append (name.str ());
107
92
93
+ SECURITY_ATTRIBUTES sa{sizeof (SECURITY_ATTRIBUTES), 0 ,
94
+ child_process_inherit ? TRUE : FALSE };
95
+
108
96
// Always open for overlapped i/o. We implement blocking manually in Read
109
97
// and Write.
110
98
DWORD read_mode = FILE_FLAG_OVERLAPPED;
111
- m_read = ::CreateNamedPipeA (
112
- pipe_path.c_str (), PIPE_ACCESS_INBOUND | read_mode,
113
- PIPE_TYPE_BYTE | PIPE_WAIT, 1 , 1024 , 1024 , 120 * 1000 , NULL );
99
+ m_read =
100
+ ::CreateNamedPipeA (pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode,
101
+ PIPE_TYPE_BYTE | PIPE_WAIT, /* nMaxInstances=*/ 1,
102
+ /* nOutBufferSize=*/ 1024,
103
+ /* nInBufferSize=*/ 1024,
104
+ /* nDefaultTimeOut=*/ 0, &sa);
114
105
if (INVALID_HANDLE_VALUE == m_read)
115
106
return Status (::GetLastError (), eErrorTypeWin32);
116
107
m_read_fd = _open_osfhandle ((intptr_t )m_read, _O_RDONLY);
@@ -155,7 +146,7 @@ Status PipeWindows::CreateWithUniqueName(llvm::StringRef prefix,
155
146
Status PipeWindows::OpenAsReader (llvm::StringRef name,
156
147
bool child_process_inherit) {
157
148
if (CanRead ())
158
- return Status (ERROR_ALREADY_EXISTS, eErrorTypeWin32);
149
+ return Status (); // Note the name is ignored.
159
150
160
151
return OpenNamedPipe (name, child_process_inherit, true );
161
152
}
@@ -165,7 +156,7 @@ PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name,
165
156
bool child_process_inherit,
166
157
const std::chrono::microseconds &timeout) {
167
158
if (CanWrite ())
168
- return Status (ERROR_ALREADY_EXISTS, eErrorTypeWin32);
159
+ return Status (); // Note the name is ignored.
169
160
170
161
return OpenNamedPipe (name, child_process_inherit, false );
171
162
}
@@ -177,8 +168,8 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
177
168
178
169
assert (is_read ? !CanRead () : !CanWrite ());
179
170
180
- SECURITY_ATTRIBUTES attributes = {};
181
- attributes. bInheritHandle = child_process_inherit;
171
+ SECURITY_ATTRIBUTES attributes{ sizeof (SECURITY_ATTRIBUTES), 0 ,
172
+ child_process_inherit ? TRUE : FALSE } ;
182
173
183
174
std::string pipe_path = g_pipe_name_prefix.str ();
184
175
pipe_path.append (name.str ());
@@ -202,6 +193,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
202
193
m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
203
194
204
195
ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
196
+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
205
197
}
206
198
207
199
return Status ();
@@ -228,6 +220,8 @@ int PipeWindows::ReleaseWriteFileDescriptor() {
228
220
return PipeWindows::kInvalidDescriptor ;
229
221
int result = m_write_fd;
230
222
m_write_fd = PipeWindows::kInvalidDescriptor ;
223
+ if (m_write_overlapped.hEvent )
224
+ ::CloseHandle (m_write_overlapped.hEvent);
231
225
m_write = INVALID_HANDLE_VALUE;
232
226
ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
233
227
return result;
@@ -250,6 +244,9 @@ void PipeWindows::CloseWriteFileDescriptor() {
250
244
if (!CanWrite ())
251
245
return ;
252
246
247
+ if (m_write_overlapped.hEvent )
248
+ ::CloseHandle (m_write_overlapped.hEvent);
249
+
253
250
_close (m_write_fd);
254
251
m_write = INVALID_HANDLE_VALUE;
255
252
m_write_fd = PipeWindows::kInvalidDescriptor ;
@@ -280,15 +277,21 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
280
277
return Status (ERROR_INVALID_HANDLE, eErrorTypeWin32);
281
278
282
279
bytes_read = 0 ;
283
- DWORD sys_bytes_read = size;
284
- BOOL result = ::ReadFile (m_read, buf, sys_bytes_read, &sys_bytes_read,
285
- &m_read_overlapped);
286
- if (!result && GetLastError () != ERROR_IO_PENDING)
287
- return Status (::GetLastError (), eErrorTypeWin32);
280
+ DWORD sys_bytes_read = 0 ;
281
+ BOOL result =
282
+ ::ReadFile (m_read, buf, size, &sys_bytes_read, &m_read_overlapped);
283
+ if (result) {
284
+ bytes_read = sys_bytes_read;
285
+ return Status ();
286
+ }
287
+
288
+ DWORD failure_error = ::GetLastError ();
289
+ if (failure_error != ERROR_IO_PENDING)
290
+ return Status (failure_error, eErrorTypeWin32);
288
291
289
292
DWORD timeout = (duration == std::chrono::microseconds::zero ())
290
293
? INFINITE
291
- : duration.count () * 1000 ;
294
+ : duration.count () / 1000 ;
292
295
DWORD wait_result = ::WaitForSingleObject (m_read_overlapped.hEvent , timeout);
293
296
if (wait_result != WAIT_OBJECT_0) {
294
297
// The operation probably failed. However, if it timed out, we need to
@@ -298,10 +301,10 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
298
301
// happens, the original operation should be considered to have been
299
302
// successful.
300
303
bool failed = true ;
301
- DWORD failure_error = ::GetLastError ();
304
+ failure_error = ::GetLastError ();
302
305
if (wait_result == WAIT_TIMEOUT) {
303
- BOOL cancel_result = CancelIoEx (m_read, &m_read_overlapped);
304
- if (!cancel_result && GetLastError () == ERROR_NOT_FOUND)
306
+ BOOL cancel_result = :: CancelIoEx (m_read, &m_read_overlapped);
307
+ if (!cancel_result && :: GetLastError () == ERROR_NOT_FOUND)
305
308
failed = false ;
306
309
}
307
310
if (failed)
@@ -310,27 +313,61 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
310
313
311
314
// Now we call GetOverlappedResult setting bWait to false, since we've
312
315
// already waited as long as we're willing to.
313
- if (!GetOverlappedResult (m_read, &m_read_overlapped, &sys_bytes_read, FALSE ))
316
+ if (!::GetOverlappedResult (m_read, &m_read_overlapped, &sys_bytes_read,
317
+ FALSE ))
314
318
return Status (::GetLastError (), eErrorTypeWin32);
315
319
316
320
bytes_read = sys_bytes_read;
317
321
return Status ();
318
322
}
319
323
320
- Status PipeWindows::Write (const void *buf, size_t num_bytes,
321
- size_t &bytes_written) {
324
+ Status PipeWindows::WriteWithTimeout (const void *buf, size_t size,
325
+ const std::chrono::microseconds &duration,
326
+ size_t &bytes_written) {
322
327
if (!CanWrite ())
323
328
return Status (ERROR_INVALID_HANDLE, eErrorTypeWin32);
324
329
325
- DWORD sys_bytes_written = 0 ;
326
- BOOL write_result = ::WriteFile (m_write, buf, num_bytes, &sys_bytes_written,
327
- &m_write_overlapped);
328
- if (!write_result && GetLastError () != ERROR_IO_PENDING)
329
- return Status (::GetLastError (), eErrorTypeWin32);
330
+ bytes_written = 0 ;
331
+ DWORD sys_bytes_write = 0 ;
332
+ BOOL result =
333
+ ::WriteFile (m_write, buf, size, &sys_bytes_write, &m_write_overlapped);
334
+ if (result) {
335
+ bytes_written = sys_bytes_write;
336
+ return Status ();
337
+ }
338
+
339
+ DWORD failure_error = ::GetLastError ();
340
+ if (failure_error != ERROR_IO_PENDING)
341
+ return Status (failure_error, eErrorTypeWin32);
330
342
331
- BOOL result = GetOverlappedResult (m_write, &m_write_overlapped,
332
- &sys_bytes_written, TRUE );
333
- if (!result)
343
+ DWORD timeout = (duration == std::chrono::microseconds::zero ())
344
+ ? INFINITE
345
+ : duration.count () / 1000 ;
346
+ DWORD wait_result = ::WaitForSingleObject (m_write_overlapped.hEvent , timeout);
347
+ if (wait_result != WAIT_OBJECT_0) {
348
+ // The operation probably failed. However, if it timed out, we need to
349
+ // cancel the I/O. Between the time we returned from WaitForSingleObject
350
+ // and the time we call CancelIoEx, the operation may complete. If that
351
+ // hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. If that
352
+ // happens, the original operation should be considered to have been
353
+ // successful.
354
+ bool failed = true ;
355
+ failure_error = ::GetLastError ();
356
+ if (wait_result == WAIT_TIMEOUT) {
357
+ BOOL cancel_result = ::CancelIoEx (m_write, &m_write_overlapped);
358
+ if (!cancel_result && ::GetLastError () == ERROR_NOT_FOUND)
359
+ failed = false ;
360
+ }
361
+ if (failed)
362
+ return Status (failure_error, eErrorTypeWin32);
363
+ }
364
+
365
+ // Now we call GetOverlappedResult setting bWait to false, since we've
366
+ // already waited as long as we're willing to.
367
+ if (!::GetOverlappedResult (m_write, &m_write_overlapped, &sys_bytes_write,
368
+ FALSE ))
334
369
return Status (::GetLastError (), eErrorTypeWin32);
370
+
371
+ bytes_written = sys_bytes_write;
335
372
return Status ();
336
373
}
0 commit comments