Getting the pipe guard

Lev Bishop
Sun May 21 01:43:00 GMT 2006

I was trying to make nonblocking pipe reads actually not block. Here's
an example of the problem:

bash-3.1$ exec 8< <(while :; do sleep 1 ; echo -n \* ; done )
bash-3.1$ cat <&8 >/dev/null &
[2] 308
bash-3.1$ dd iflag=nonblock bs=1 <&8
dd: reading `standard input': Resource temporarily unavailable
0+0 records in
0+0 records out
0 bytes (0 B) copied, 3.2 seconds, 0.0 kB/s

I tracked down the problem and made the attached patch to get the
guard mutex, which I believe was cgf's intention when he put get_guard
(I'm guessing from the changelogs, here), since the previous code was
a no-op.

2006-05-15 Lev Bishop <>
	* (fhandler_pipe::ready_for_read): Actually get the
	guard mutex.

However, although this improves things, the "nonblocking" read can
still block for the duration of one read in the other process. I
deduce that, despite the msdn article on PeekNamedPipe:
> The function always returns immediately, even if there is no data in the
> pipe. The wait mode of a named pipe handle (blocking or nonblocking) has
> no effect on the function.
...actually it can block for the duration of another process's
blocking read. Presumably, windows has an internal guard mutex of it's

There are 2 questions I have related to this:
1) Why does cygwin go to all the trouble of having guard mutexes and
so on for it's pipes, to simulate nonblocking operations (imperfectly
for pipe reads, not at all for pipe writes) when there's the
PIPE_NOWAIT flag available which appears to do it in a built-in
fashion? Has this been considered and rejected for some reason I can't
think of?
2) In my example above I had 2 descriptors to the same pipe, one set
blocking and one nonblocking. Unix behaviour doesn't allow this
because O_NONBLOCK applies to the file description, not to a
particular file descriptor. The same goes for O_APPEND, O_ASYNC, etc.
For full unix compatibility these flags (and I would guess various
parts of the fhandler_xxx structures, like my fhandler_socket::chunk)
would have to be put in shared regions or similar. Has something like
this been contemplated?

Consider this patch untested at present.

-------------- next part --------------
RCS file: /cvs/src/src/winsup/cygwin/,v
retrieving revision 1.123
diff -u -p -d -r1.123
---	24 Apr 2006 15:16:45 -0000	1.123
+++	21 May 2006 00:56:04 -0000
@@ -689,14 +689,18 @@ pipe_cleanup (select_record *, select_st
 fhandler_pipe::ready_for_read (int fd, DWORD howlong)
-  int res;
+  int res = true;
+  const HANDLE w4[2] = {signal_arrived, get_guard ()};
   if (howlong)
-    res = true;
+    {
+      if (w4[2] && WAIT_OBJECT_0 == WaitForMultipleObjects (2, w4, 0, INFINITE))
+	{
+	  set_sig_errno (EINTR);
+	  return 0;
+	}
+    }
     res = fhandler_base::ready_for_read (fd, howlong);
-  if (res)
-    get_guard ();
   return res;

More information about the Cygwin-patches mailing list