@@ -58,7 +58,10 @@ 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 (); }
@@ -77,6 +80,7 @@ Status PipeWindows::CreateNew(bool child_process_inherit) {
77
80
78
81
m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
79
82
ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
83
+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
80
84
81
85
return Status ();
82
86
}
@@ -202,6 +206,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
202
206
m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
203
207
204
208
ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
209
+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
205
210
}
206
211
207
212
return Status ();
@@ -228,6 +233,8 @@ int PipeWindows::ReleaseWriteFileDescriptor() {
228
233
return PipeWindows::kInvalidDescriptor ;
229
234
int result = m_write_fd;
230
235
m_write_fd = PipeWindows::kInvalidDescriptor ;
236
+ if (m_write_overlapped.hEvent )
237
+ ::CloseHandle (m_write_overlapped.hEvent);
231
238
m_write = INVALID_HANDLE_VALUE;
232
239
ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
233
240
return result;
@@ -250,6 +257,9 @@ void PipeWindows::CloseWriteFileDescriptor() {
250
257
if (!CanWrite ())
251
258
return ;
252
259
260
+ if (m_write_overlapped.hEvent )
261
+ ::CloseHandle (m_write_overlapped.hEvent);
262
+
253
263
_close (m_write_fd);
254
264
m_write = INVALID_HANDLE_VALUE;
255
265
m_write_fd = PipeWindows::kInvalidDescriptor ;
@@ -283,54 +293,94 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
283
293
DWORD sys_bytes_read = size;
284
294
BOOL result = ::ReadFile (m_read, buf, sys_bytes_read, &sys_bytes_read,
285
295
&m_read_overlapped);
286
- if (!result && GetLastError () != ERROR_IO_PENDING)
287
- return Status (::GetLastError (), eErrorTypeWin32);
288
-
289
- DWORD timeout = (duration == std::chrono::microseconds::zero ())
290
- ? INFINITE
291
- : duration.count () * 1000 ;
292
- DWORD wait_result = ::WaitForSingleObject (m_read_overlapped.hEvent , timeout);
293
- if (wait_result != WAIT_OBJECT_0) {
294
- // The operation probably failed. However, if it timed out, we need to
295
- // cancel the I/O. Between the time we returned from WaitForSingleObject
296
- // and the time we call CancelIoEx, the operation may complete. If that
297
- // hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. If that
298
- // happens, the original operation should be considered to have been
299
- // successful.
300
- bool failed = true ;
301
- DWORD failure_error = ::GetLastError ();
302
- if (wait_result == WAIT_TIMEOUT) {
303
- BOOL cancel_result = CancelIoEx (m_read, &m_read_overlapped);
304
- if (!cancel_result && GetLastError () == ERROR_NOT_FOUND)
305
- failed = false ;
296
+ if (!result) {
297
+ if (GetLastError () != ERROR_IO_PENDING)
298
+ return Status (::GetLastError (), eErrorTypeWin32);
299
+ else {
300
+ DWORD timeout = (duration == std::chrono::microseconds::zero ())
301
+ ? INFINITE
302
+ : duration.count () * 1000 ;
303
+ DWORD wait_result =
304
+ ::WaitForSingleObject (m_read_overlapped.hEvent, timeout);
305
+ if (wait_result != WAIT_OBJECT_0) {
306
+ // The operation probably failed. However, if it timed out, we need to
307
+ // cancel the I/O. Between the time we returned from WaitForSingleObject
308
+ // and the time we call CancelIoEx, the operation may complete. If that
309
+ // hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. If that
310
+ // happens, the original operation should be considered to have been
311
+ // successful.
312
+ bool failed = true ;
313
+ DWORD failure_error = ::GetLastError ();
314
+ if (wait_result == WAIT_TIMEOUT) {
315
+ BOOL cancel_result = CancelIoEx (m_read, &m_read_overlapped);
316
+ if (!cancel_result && GetLastError () == ERROR_NOT_FOUND)
317
+ failed = false ;
318
+ }
319
+ if (failed)
320
+ return Status (failure_error, eErrorTypeWin32);
321
+ }
322
+
323
+ // Now we call GetOverlappedResult setting bWait to false, since we've
324
+ // already waited as long as we're willing to.
325
+ if (!GetOverlappedResult (m_read, &m_read_overlapped, &sys_bytes_read,
326
+ FALSE ))
327
+ return Status (::GetLastError (), eErrorTypeWin32);
306
328
}
307
- if (failed)
308
- return Status (failure_error, eErrorTypeWin32);
309
329
}
310
-
311
- // Now we call GetOverlappedResult setting bWait to false, since we've
312
- // already waited as long as we're willing to.
313
- if (!GetOverlappedResult (m_read, &m_read_overlapped, &sys_bytes_read, FALSE ))
314
- return Status (::GetLastError (), eErrorTypeWin32);
315
-
316
330
bytes_read = sys_bytes_read;
317
331
return Status ();
318
332
}
319
333
320
- Status PipeWindows::Write (const void *buf, size_t num_bytes,
321
- size_t &bytes_written) {
334
+ Status PipeWindows::WriteWithTimeout (const void *buf, size_t size,
335
+ const std::chrono::microseconds &duration,
336
+ size_t &bytes_written) {
322
337
if (!CanWrite ())
323
338
return Status (ERROR_INVALID_HANDLE, eErrorTypeWin32);
324
339
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);
340
+ bytes_written = 0 ;
341
+ DWORD sys_bytes_write = size;
342
+ BOOL result = ::WriteFile (m_write, buf, sys_bytes_write, &sys_bytes_write,
343
+ &m_write_overlapped);
344
+ if (!result) {
345
+ if (GetLastError () != ERROR_IO_PENDING)
346
+ return Status (::GetLastError (), eErrorTypeWin32);
347
+ else {
348
+ DWORD timeout = (duration == std::chrono::microseconds::zero ())
349
+ ? INFINITE
350
+ : duration.count () * 1000 ;
351
+ DWORD wait_result =
352
+ ::WaitForSingleObject (m_write_overlapped.hEvent, timeout);
353
+ if (wait_result != WAIT_OBJECT_0) {
354
+ // The operation probably failed. However, if it timed out, we need to
355
+ // cancel the I/O. Between the time we returned from WaitForSingleObject
356
+ // and the time we call CancelIoEx, the operation may complete. If that
357
+ // hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. If that
358
+ // happens, the original operation should be considered to have been
359
+ // successful.
360
+ bool failed = true ;
361
+ DWORD failure_error = ::GetLastError ();
362
+ if (wait_result == WAIT_TIMEOUT) {
363
+ BOOL cancel_result = CancelIoEx (m_write, &m_write_overlapped);
364
+ if (!cancel_result && GetLastError () == ERROR_NOT_FOUND)
365
+ failed = false ;
366
+ }
367
+ if (failed)
368
+ return Status (failure_error, eErrorTypeWin32);
369
+ }
370
+
371
+ // Now we call GetOverlappedResult setting bWait to false, since we've
372
+ // already waited as long as we're willing to.
373
+ if (!GetOverlappedResult (m_write, &m_write_overlapped, &sys_bytes_write,
374
+ FALSE ))
375
+ return Status (::GetLastError (), eErrorTypeWin32);
376
+ }
377
+ }
330
378
331
- BOOL result = GetOverlappedResult (m_write, &m_write_overlapped,
332
- &sys_bytes_written, TRUE );
333
- if (!result)
334
- return Status (::GetLastError (), eErrorTypeWin32);
379
+ bytes_written = sys_bytes_write;
335
380
return Status ();
336
381
}
382
+
383
+ Status PipeWindows::Write (const void *buf, size_t size, size_t &bytes_written) {
384
+ return WriteWithTimeout (buf, size, std::chrono::microseconds::zero (),
385
+ bytes_written);
386
+ }
0 commit comments