delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2012/04/24/10:08:53

X-Recipient: archive-cygwin AT delorie DOT com
X-Spam-Check-By: sourceware.org
Date: Tue, 24 Apr 2012 16:07:52 +0200
From: Corinna Vinschen <corinna-cygwin AT cygwin DOT com>
To: cygwin AT cygwin DOT com
Subject: Re: 1.7.10->1.7.13 : output from .NET programs does not get through pipeline to a visual c++ program
Message-ID: <20120424140752.GH25385@calimero.vinschen.de>
Reply-To: cygwin AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
References: <CAHxe11=J=cJnwWcRnA1Pi9CmezWw+z04-b5k4trVmE3mVbiH7A AT mail DOT gmail DOT com> <CAHxe11=DBVftZ15xCLjnaEFYVESqggezJtx2EJNK2ZTUrMUNdQ AT mail DOT gmail DOT com> <00e101cd1f09$83405310$89c0f930$@motionview3d.com> <CAHxe11=ixmncGgNby3+RZspVQT6DxnFuTbCgH4si=yRk1EhmyQ AT mail DOT gmail DOT com>
MIME-Version: 1.0
In-Reply-To: <CAHxe11=ixmncGgNby3+RZspVQT6DxnFuTbCgH4si=yRk1EhmyQ@mail.gmail.com>
User-Agent: Mutt/1.5.21 (2010-09-15)
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Unsubscribe: <mailto:cygwin-unsubscribe-archive-cygwin=delorie DOT com AT cygwin DOT com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com


Please don't http://cygwin.com/acronyms/#TOFU
Thank you.


On Apr 24 13:37, cygwin AT alanhowells DOT e4ward DOT com wrote:
> Thank you very much James for the helpful comments and pointer to your
> sample program.
> 
> I have some more information and I tried to minimise .NET and so wrote
> the program in C++, compiled with "cl /EHs consoleout.cxx /link"
> 
> >>> begin consoleout.cxx
> #include <windows.h>
> 
> int
> main(int argc, char* argv[])
> {
>     DWORD written;
> 
>     // Get standard output file handle
>     HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
> 
>     // Do a null write.  This is what .net does.
>     WriteFile(h, "", 0, &written, NULL);
> 
>     for (int i = 1; i < argc; ++i) {
>         DWORD toWrite = strlen(argv[i]);
>     	WriteFile(h, argv[i], toWrite, &written, NULL);
>     	WriteFile(h, "\n", 1, &written, NULL);
>     }
> 
>     return EXIT_SUCCESS;
> }
> <<< end consoleout.cxx
> 
> The strange thing here is that I get the issue on the first time (but
> not the second or third):
> $ ./consoleout hello world | ./readin
> $ ./consoleout hello world | ./readin
> hello
> world
> $ ./consoleout hello world | ./readin
> hello
> world
> $

This problem has nothing to do with Cygwin, as far as I can see.  What
happens is that the shell creates the pipe for you and then starts two
native Child processes, consoleout and readin, which use the existing
pipe without any interference from Cygwin.

So you have to look into the testcases itself to find the cause for the
problem.  And here we go:

> >>> begin readin.cxx
> #include <windows.h>
> 
> int
> main(int argc, char* argv[])
> {
>     static_cast<void>(argc);
>     static_cast<void>(argv);
> 
>     HANDLE hi = GetStdHandle(STD_INPUT_HANDLE);
>     HANDLE ho = GetStdHandle(STD_OUTPUT_HANDLE);
> 
>     char buf[1024];
>     DWORD read, written;
>     ReadFile(hi, buf, 1024, &read, NULL);
>     WriteFile(ho, buf, read, &written, NULL);
> 
>     return EXIT_SUCCESS;
> }
> >>> end readin.cxx

So, while your writer *writes* a 0 bytes block, your reader doesn't
*expect* a 0 bytes block, even though that's exactly what this case is
about.  Even worse, your readin testcase doesn't expect short reads at
all.  Consider the processes are scheduled interlaced:

  WriteFile ("");
                    ReadFile();
  WriteFile ("hello");
                    ReadFile();
  WriteFile ("\n");
                    ReadFile();
  WriteFile ("world");
                    ReadFile();
  WriteFile ("\n");
                    ReadFile();

If you change your application accordingly, it will work as expected:

  #include <windows.h>
  
  int
  main(int argc, char* argv[])
  {
      static_cast<void>(argc);
      static_cast<void>(argv);
  
      HANDLE hi = GetStdHandle(STD_INPUT_HANDLE);
      HANDLE ho = GetStdHandle(STD_OUTPUT_HANDLE);
  
      char buf[1024];
      DWORD read, written;
      BOOL ret;

      do
        {
	  ret = ReadFile(hi, buf, 1024, &read, NULL);
	  if (ret && read > 0)
	    WriteFile(ho, buf, read, &written, NULL);
	}
      while (ret);
  
      return EXIT_SUCCESS;
  }


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019