This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: 1.7.10->1.7.13 : output from .NET programs does not get through pipeline to a visual c++ program



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


On Apr 24 13:37, cygwin@alanhowells.e4ward.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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]