public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Patrick Doyle <wpd@delcomsys.com>
To: cygwin <cygwin@cygwin.com>
Subject: Re: Why does scp leave ssh running? -- select() never returns
Date: Mon, 11 Dec 2000 10:19:00 -0000	[thread overview]
Message-ID: <3A351ADE.EF54C845@delcomsys.com> (raw)
In-Reply-To: <3A2A16B5.E1C3F9F4@redhat.com>

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@sourceware.cygnus.com

  reply	other threads:[~2000-12-11 10:19 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-11-27 12:26 Why does scp leave ssh running? Patrick Doyle
2000-11-28  2:12 ` Graham Bloice
2000-11-29 19:21 ` Why does scp leave ssh running? -- select() never returns Patrick Doyle
2000-11-29 19:41   ` Christopher Faylor
2000-11-30  6:15     ` Patrick Doyle
2000-11-30  6:35       ` Corinna Vinschen
2000-11-30  7:05         ` Patrick Doyle
2000-11-30 19:40       ` Patrick Doyle
2000-12-02 17:08         ` Christopher Faylor
2000-12-02 19:47           ` Patrick Doyle
2000-12-02 20:39             ` Christopher Faylor
2000-12-03  1:47               ` Corinna Vinschen
2000-12-11 10:19                 ` Patrick Doyle [this message]
2000-12-11 10:36                   ` Christopher Faylor
2000-12-11 10:56                     ` Patrick Doyle
2000-12-11 11:08                       ` Christopher Faylor
2001-01-06 19:21                       ` Patrick Doyle
2001-01-08  3:21                         ` Ehud Karni
2001-01-08  6:24                           ` Patrick Doyle
2000-12-12  5:46                   ` David Starks-Browning

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=3A351ADE.EF54C845@delcomsys.com \
    --to=wpd@delcomsys.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).