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 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: <00e101cd1f09$83405310$89c0f930$@motionview3d.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , 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 > > 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 > > int > main(int argc, char* argv[]) > { > static_cast(argc); > static_cast(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 int main(int argc, char* argv[]) { static_cast(argc); static_cast(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