@@ -58,30 +58,15 @@ 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 (); }
6568
6669Status 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) {
8570 // Even for anonymous pipes, we open a named pipe. This is because you
8671 // cannot get overlapped i/o on Windows without using a named pipe. So we
8772 // synthesize a unique name.
@@ -105,12 +90,18 @@ Status PipeWindows::CreateNew(llvm::StringRef name,
10590 std::string pipe_path = g_pipe_name_prefix.str ();
10691 pipe_path.append (name.str ());
10792
93+ SECURITY_ATTRIBUTES sa{sizeof (SECURITY_ATTRIBUTES), 0 ,
94+ child_process_inherit ? TRUE : FALSE };
95+
10896 // Always open for overlapped i/o. We implement blocking manually in Read
10997 // and Write.
11098 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);
114105 if (INVALID_HANDLE_VALUE == m_read)
115106 return Status (::GetLastError (), eErrorTypeWin32);
116107 m_read_fd = _open_osfhandle ((intptr_t )m_read, _O_RDONLY);
@@ -155,7 +146,7 @@ Status PipeWindows::CreateWithUniqueName(llvm::StringRef prefix,
155146Status PipeWindows::OpenAsReader (llvm::StringRef name,
156147 bool child_process_inherit) {
157148 if (CanRead ())
158- return Status (ERROR_ALREADY_EXISTS, eErrorTypeWin32);
149+ return Status (); // Note the name is ignored.
159150
160151 return OpenNamedPipe (name, child_process_inherit, true );
161152}
@@ -165,7 +156,7 @@ PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name,
165156 bool child_process_inherit,
166157 const std::chrono::microseconds &timeout) {
167158 if (CanWrite ())
168- return Status (ERROR_ALREADY_EXISTS, eErrorTypeWin32);
159+ return Status (); // Note the name is ignored.
169160
170161 return OpenNamedPipe (name, child_process_inherit, false );
171162}
@@ -177,8 +168,8 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
177168
178169 assert (is_read ? !CanRead () : !CanWrite ());
179170
180- SECURITY_ATTRIBUTES attributes = {};
181- attributes. bInheritHandle = child_process_inherit;
171+ SECURITY_ATTRIBUTES attributes{ sizeof (SECURITY_ATTRIBUTES), 0 ,
172+ child_process_inherit ? TRUE : FALSE } ;
182173
183174 std::string pipe_path = g_pipe_name_prefix.str ();
184175 pipe_path.append (name.str ());
@@ -202,6 +193,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
202193 m_write_fd = _open_osfhandle ((intptr_t )m_write, _O_WRONLY);
203194
204195 ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
196+ m_write_overlapped.hEvent = ::CreateEventA (nullptr , TRUE , FALSE , nullptr );
205197 }
206198
207199 return Status ();
@@ -228,6 +220,8 @@ int PipeWindows::ReleaseWriteFileDescriptor() {
228220 return PipeWindows::kInvalidDescriptor ;
229221 int result = m_write_fd;
230222 m_write_fd = PipeWindows::kInvalidDescriptor ;
223+ if (m_write_overlapped.hEvent )
224+ ::CloseHandle (m_write_overlapped.hEvent);
231225 m_write = INVALID_HANDLE_VALUE;
232226 ZeroMemory (&m_write_overlapped, sizeof (m_write_overlapped));
233227 return result;
@@ -250,6 +244,9 @@ void PipeWindows::CloseWriteFileDescriptor() {
250244 if (!CanWrite ())
251245 return ;
252246
247+ if (m_write_overlapped.hEvent )
248+ ::CloseHandle (m_write_overlapped.hEvent);
249+
253250 _close (m_write_fd);
254251 m_write = INVALID_HANDLE_VALUE;
255252 m_write_fd = PipeWindows::kInvalidDescriptor ;
@@ -280,15 +277,21 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
280277 return Status (ERROR_INVALID_HANDLE, eErrorTypeWin32);
281278
282279 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);
288291
289292 DWORD timeout = (duration == std::chrono::microseconds::zero ())
290293 ? INFINITE
291- : duration.count () * 1000 ;
294+ : duration.count () / 1000 ;
292295 DWORD wait_result = ::WaitForSingleObject (m_read_overlapped.hEvent , timeout);
293296 if (wait_result != WAIT_OBJECT_0) {
294297 // The operation probably failed. However, if it timed out, we need to
@@ -298,10 +301,10 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
298301 // happens, the original operation should be considered to have been
299302 // successful.
300303 bool failed = true ;
301- DWORD failure_error = ::GetLastError ();
304+ failure_error = ::GetLastError ();
302305 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)
305308 failed = false ;
306309 }
307310 if (failed)
@@ -310,27 +313,61 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
310313
311314 // Now we call GetOverlappedResult setting bWait to false, since we've
312315 // 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 ))
314318 return Status (::GetLastError (), eErrorTypeWin32);
315319
316320 bytes_read = sys_bytes_read;
317321 return Status ();
318322}
319323
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) {
322327 if (!CanWrite ())
323328 return Status (ERROR_INVALID_HANDLE, eErrorTypeWin32);
324329
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);
330342
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 ))
334369 return Status (::GetLastError (), eErrorTypeWin32);
370+
371+ bytes_written = sys_bytes_write;
335372 return Status ();
336373}
0 commit comments