Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <3A351ADE.EF54C845@delcomsys.com> Date: Mon, 11 Dec 2000 13:20:14 -0500 From: Patrick Doyle X-Mailer: Mozilla 4.76 [en] (Win98; U) X-Accept-Language: en,zh,zh-CN,zh-TW MIME-Version: 1.0 To: cygwin Subject: Re: Why does scp leave ssh running? -- select() never returns References: <3A22C383 DOT 5C16BBC8 AT delcomsys DOT com> <3A25C7DA DOT 6F76C8DA AT delcomsys DOT com> <20001129224015 DOT B21867 AT redhat DOT com> <3A266130 DOT F5877EB5 AT delcomsys DOT com> <3A271DCD DOT 99BDDBF5 AT delcomsys DOT com> <20001202200832 DOT A18661 AT redhat DOT com> <3A29C260 DOT 1C491A30 AT delcomsys DOT com> <20001202233944 DOT A19867 AT redhat DOT com> <3A2A16B5 DOT E1C3F9F4 AT redhat DOT com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Status update... First, to refresh the memory of those who are interested in following this thread: 1) cygwin implements pipes (i.e. the 'pipe()' system call) using Windows "anonymous pipes". 2) cygwin implements the 'select()' system call by creating a thread which wakes up every 10 ms and calls 'PeekNamedPipe()' to see if any data are available in the pipe. 3) On Windows 9x machines, 'PeekNamedPipe()' gives no indication when the writer of a pipe closes the pipe. It simply indicates that there are 0 bytes available to be read from the pipe. The only way to know that the writer has closed the pipe is to call 'ReadFile()'. On Windows NT/2K, 'PeekNamedPipe()' returns an indication that the pipe has been closed. 4) SSH uses 'select()' to determine when it is time to read from stdin. If stdin is a pipe and the writer closes the pipe, SSH does not detect this and is left waiting for more input. This happens when using "scp" and when using SSH with "cvs". 5) I have been racking my brain trying to figure out a way to solve this problem. (I posted a simple program to the list a couple of weeks ago that demonstrates this problem). So far, the most elegant solution I have come up with is to reimplement 'select()' so that it calls 'ReadFileEx()' with a suitable 'OVERLAPPED' structure, thus eliminating the separate thread that wakes up every 10 ms. Of course, if I read a byte from the pipe, I would have to buffer it somewhere and fix 'read()' so that it checks for the "readahead" byte first, but that is basically solvable. If the call to 'select()' returned for some other reason (i.e. another fd was made ready), then call 'CancelIo()' to terminate the asynchronous read. The problem with this approach is that the documentation on the MSDN web site states that, for Windows 95/98, "You cannot perform asynchronous read operations on mailslots, named pipes, or disk files", leaving the possibility that it might work on anonymous pipes. Before I expend a lot of effort on this, does anybody know if asynchronous reads of anonymous pipes are supported on 9x? If there is documentation that says that it is not supported, but experimentation indicates that it works anyway, would such an approach be incorporated into cygwin? (In other words, is cygwin willing to depend on code behavior that is unsupported by MS, specifically, behavior of 9x code -- if the answer is no, then I won't waste any effort trying to figure out if it would work). The only other viable alternative I have come up with is to open a second anonymous pipe in parallel with the first and use it to send OOB messages such as "dup occured" or "closing pipe" to the reader. I would bracket all of this code with: if (win9x) { anonymous_pipe_hack(); } so that it would not impact NT/2K users. It would not work with non-cygwin apps (on 9x machines) and could suffer from being fooled somehow. I am reminded that I meant to look into how the TTY code works, since Christopher said that it has some similar issues (and has problems working with non-cygwin apps). I have come to appreciate Christopher's statement "I hate Windows 9x." more and more as each idea I have come up with to address this problem has been shot down when I check the MSDN website and find words to the effect of "this is unsupported on Windows 95/98" in the middle of the function that I think might solve the problem. As a final note, I wondered why RSH didn't suffer from this problem. It's because it forks a separate process just to read from stdin, and doesn't call 'select()'. I keep toying with the idea of modifying SSH to do something similar, but it seems like too much work, and too much modification to SSH, to be a "good" solution. (I would fork a process that just read from stdin and wrote to stdout and then use SIGCHILD to notify the parent process that it should no longer attempt to read from stdin. If we were willing to tolerate an additional process-per-pipe on 9x machines, I could look into doing something like this automatically in cygwin, but I think I'll try my "second anonymous pipe" approach first). If anybody has bothered to continue reading this far, I just want to say that I truly appreciate the work that has gone into cygwin and that I especially like the fact that I can compile, test, and debug modifications to cygwin1.dll myself (i.e. on my W98 box). I remember the days when cygwin1.dll had to be compiled on a Linux box and then copied to the Windows box, and I am very grateful for all the work that has gone into making the tools self-hosting. Thanks again folks! --wpd -- Want to unsubscribe from this list? Send a message to cygwin-unsubscribe AT sourceware DOT cygnus DOT com