@@ -58,7 +58,10 @@ PipeWindows::PipeWindows(pipe_t read, pipe_t write)
5858 }
5959
6060 ZeroMemory (&m_read_overlapped, sizeof (m_read_overlapped));
61+ m_read_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
62+
6163 ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
64+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
6265}
6366
6467PipeWindows::~PipeWindows () { Close (); }
@@ -77,6 +80,7 @@ Status PipeWindows::CreateNew(bool child_process_inherit) {
7780
7881 m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
7982 ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
83+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
8084
8185 return Status ();
8286}
@@ -202,6 +206,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
202206 m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
203207
204208 ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
209+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
205210 }
206211
207212 return Status ();
@@ -228,6 +233,8 @@ int PipeWindows::ReleaseWriteFileDescriptor() {
228233 return PipeWindows::kInvalidDescriptor ;
229234 int result = m_write_fd;
230235 m_write_fd = PipeWindows::kInvalidDescriptor ;
236+ if (m_write_overlapped.hEvent )
237+ ::CloseHandle (m_write_overlapped.hEvent);
231238 m_write = INVALID_HANDLE_VALUE;
232239 ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
233240 return result;
@@ -250,6 +257,9 @@ void PipeWindows::CloseWriteFileDescriptor() {
250257 if (!CanWrite ())
251258 return ;
252259
260+ if (m_write_overlapped.hEvent )
261+ ::CloseHandle (m_write_overlapped.hEvent);
262+
253263 _close (m_write_fd);
254264 m_write = INVALID_HANDLE_VALUE;
255265 m_write_fd = PipeWindows::kInvalidDescriptor ;
@@ -283,54 +293,94 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
283293 DWORD sys_bytes_read = size;
284294 BOOL result = ::ReadFile (m_read, buf, sys_bytes_read, &sys_bytes_read,
285295 &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);
306328 }
307- if (failed)
308- return Status (failure_error, eErrorTypeWin32);
309329 }
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-
316330 bytes_read = sys_bytes_read;
317331 return Status ();
318332}
319333
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) {
322337 if (!CanWrite ())
323338 return Status (ERROR_INVALID_HANDLE, eErrorTypeWin32);
324339
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+ }
330378
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;
335380 return Status ();
336381}
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