Pipe syncronization and incompatibility between Cygwin and .NET Framework 4.0

James Johnston JamesJ@motionview3d.com
Mon Dec 23 23:06:00 GMT 2013

> I am calling a few different .NET Framework 4.0 command line tools from
> Cygwin and have noted that .NET Framework 4.0 introduced a change that
> causes an incompatibility between it and Cygwin.  I have carefully
> .NET Framework 4.0 source code and also checked things out with an API
> monitor utility, and have arrived at a simple test case in straight Win32
> code.
> <snip test case that calls WaitForSingleObject with unsupported pipe
> Then run this from bash shell:
> ( sleep 3 ; echo test ) | ./ReaderCPP
> This issue will affect every .NET Framework 4.0 program that attempts to
> read from standard input.

I narrowed down the problem.  The stdin file handle inherited by the
non-Cygwin program ReaderCPP is an overlapped file handle.  I wrote a simple
Win32 C test case that uses CreateNamedPipe & CreateFile like Cygwin does in
fhandler_pipe::create in pipes.cc file.  The test case opens both handles
with FILE_FLAG_OVERLAPPED.  It then calls CreateProcess to start WriterCPP
(containing a Sleep & a WriteFile to stdout) and the existing ReaderCPP
program.  The pipe is used to connect WriterCPP's stdout to ReaderCPP's
stdin.  This causes ReaderCPP to hang, just like it was when called from
Cygwin.  If I remove the problematic WaitForMultipleObjectsEx call from
ReaderCPP, then everything works normally.  Alternatively, if I modify the
program to NOT open pipes in overlapped mode, the WaitForMultipleObjectsEx
is no longer a problem - pointing to the solution.  I can send sample code
if it would be helpful to anyone.

As far as I'm aware, this practice of passing overlapped standard file
handles to Win32 child processes is probably unique to Cygwin.  The standard
CMD.EXE doesn't do it, for example.  One reason why this probably MUST be
the case is given in the MSDN docs for ReadFile:

"A pointer to an OVERLAPPED structure is required if the hFile parameter was
opened with FILE_FLAG_OVERLAPPED, otherwise it can be NULL."

This is further confirmed in the remarks ("The lpOverlapped parameter must
not be NULL").  Because probably every Win32 program in existence isn't
normally using overlapped I/O with their standard file handles, this causes
all of them to exhibit undefined behavior.

The bottom line is that .NET Framework 4.0 programs will hang when they try
to read from standard input unless Cygwin can give them pipe handles that
were NOT opened with overlapped I/O.  Also, any standard Win32 program will
exhibit undefined behavior because most (all?) Win32 C runtime libraries do
not use overlapped I/O with the standard file handles.  This will require
modifications to Cygwin.  It seems that fhandler_pipe::create needs to NOT
create overlapped pipes - at least in the case of pipes destined for
standard Win32 programs' stdin.  That might be easier said than done,
however.  On the other hand, a blanket change of removing
FILE_FLAG_OVERLAPPED carries the risk of breaking existing code in Cygwin -
I don't know how catastrophic such a change might be.

Any ideas?  If removing this flag causes breakage only in rare edge cases or
results in non-POSIX behavior (or no breakage at all), perhaps this behavior
can be customized via a flag in the CYGWIN environment variable.  On the
other hand, if removing the flag causes mass breakage, I am not sure what
the solution should be.

Best regards,

James Johnston

Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

More information about the Cygwin mailing list