public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Christopher Faylor <cgf-use-the-mailinglist-please@cygwin.com>
To: cygwin@cygwin.com
Subject: Re: Cygwin passes through null writes to other software when redirecting standard input/output (i.e. piping)
Date: Fri, 27 Apr 2012 00:17:00 -0000	[thread overview]
Message-ID: <20120427001718.GA10533@ednor.casa.cgf.cx> (raw)
In-Reply-To: <020501cd23f2$20f07620$62d16260$@motionview3d.com>

On Thu, Apr 26, 2012 at 09:18:27PM -0000, James Johnston wrote:
>========== SenderC.c: Sender program in Visual C++ 2008 ==========
>
>#include <windows.h>
>int main() {
>	char * test = "Hello world!\n";
>	DWORD written;
>	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); /* Get standard output
>file handle */
>	Sleep(1000); /* wait for pipes to set up and for receiving app to
>block on first ReadFile call */
>	WriteFile(h, test, 0, &written, NULL); /* do null write */
>	Sleep(1000); /* wait for receiving app to get the null write */
>	WriteFile(h, test, lstrlenA(test), &written, NULL); /* print hello
>message */
>	return 0;
>}
>
>========== ReceiverCPP.cpp: Receiver program in Visual C++ 2008 that
>demonstrates bug in VC++ 2008 runtime / STL ==========
>
>#include <iostream>
>#include <string>
>using namespace std;
>int main() {
>	/* you have to use a retry loop, for exact same reasons given for C#
>receiver program:
>	there is no way to tell difference between end-of-file and null
>write. */
>	for (int i = 0; i < 10; i++) {
>		string str;
>		/* BUG: cin will indicate end-of-file on a null write. */
>		getline(cin, str);
>		if (cin.eof()) {
>			cout << "Got end-of-file" << endl;
>		} else {
>			cout << "Got line " << str << endl;
>		}
>		cin.clear(); /* future getline calls will always immediately
>fail without attempting another read unless we clear EOF/fail flags */
>	}
>	return 0;
>}
>
>========== Test results ==========
>
>The test programs are designed so that they can be run in any combination
>from the command prompt.  The output from a sender is piped to the input of
>a receiver.  Each combination delivers identical output to the other
>combinations:
>
> * ./SenderCS | ./ReceiverCS
> * ./SenderCS | ./ReceiverCPP
> * ./SenderC | ./ReceiverCS
> * ./SenderC | ./ReceiverCPP
>
>Output from Cygwin will always be:
>
>Got end-of-file
>Got line Hello world!
>Got end-of-file
>Got end-of-file
><snip>

Nope, it won't always be that because I get what's expected.  I built
the C++ files using mingw g++.  Although I actually expected the reader
to honor the null byte, it did not.  Perhaps you are using a different
version of Windows than I am or a different runtime.

What you are seeing may be because Cygwin was changed to use
message-type pipes a couple of revisions ago.  This is not going to
change.  The change was adopted to fix a problem with Cygwin programs
and those are obviously our #1 priority.

>This is wrong, because the program received end-of-file before it was
>actually at the end of the input stream, due to the bug in its runtime's
>handling of return values from ReadFile API.  I did not do any tests using
>standard error, but I assume Cygwin redirects standard error in the same way
>it redirects standard output, in which case it would have the same problem.
>
>[moved]
>
>I think a workable fix would be for Cygwin not to pass through null writes
>it receives on an output/error pipe.  For example, somewhere in Cygwin I
>assume there is a loop that calls ReadFile to read the redirected standard
>output from the first program, and then calls WriteFile to send this output
>to the second program's standard input.  If the call to WriteFile was
>skipped if it would write zero bytes (i.e. so Cygwin doesn't do null writes
>itself), I think it would fix the problem and work around all these buggy
>runtimes.

There's no way that Cygwin could know to "skip" a call to WriteFile().
Cygwin doesn't interpose itself in the middle of a pipe.  That would be
truly disastrous.  If it somehow looked at every pipe read/write rather
than just allowing I/O to flow from one end to the other, the mailing
list would be even more filled with people complaining that Cygwin is
slow.

--
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

  reply	other threads:[~2012-04-27  0:17 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-26 21:19 James Johnston
2012-04-27  0:17 ` Christopher Faylor [this message]
2012-04-27 14:26   ` James Johnston
2012-04-27 16:28     ` Christopher Faylor
2012-04-27 15:12   ` jojelino
2012-04-27 16:28     ` Christopher Faylor
2012-04-27  9:09 ` cygwin
2012-04-27 14:41   ` Christopher Faylor
2012-04-27 14:38 ` Corinna Vinschen
2012-04-27 22:38   ` James Johnston
2012-04-28  0:25     ` Daniel Colascione
2012-04-28  5:27       ` Christopher Faylor
2012-04-28 11:20         ` Daniel Colascione
2012-05-09 19:00           ` Linda Walsh
2012-05-09 19:21             ` James Johnston
2012-05-09 20:12               ` Christopher Faylor
2012-05-10 16:28                 ` James Johnston
2012-05-10 16:33                   ` Otto Meta
2012-05-10 17:57                   ` Earnie Boyd
2012-05-10 18:39                     ` Corinna Vinschen
2012-05-11  9:05                       ` Andrey Repin
2012-05-11  3:34                 ` Daniel Colascione
2012-05-11  5:08               ` Linda Walsh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120427001718.GA10533@ednor.casa.cgf.cx \
    --to=cgf-use-the-mailinglist-please@cygwin.com \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).