sshd fails to close open file descriptors when forking

Ed Phillips ed at UDel.Edu
Tue Oct 23 03:04:52 EST 2001


On Mon, 22 Oct 2001, Lutz Jaenicke wrote:

> Date: Mon, 22 Oct 2001 17:22:46 +0200
> From: Lutz Jaenicke <Lutz.Jaenicke at aet.TU-Cottbus.DE>
> To: openssh-unix-dev at mindrot.org
> Subject: Re: sshd fails to close open file descriptors when forking
>
> On Mon, Oct 22, 2001 at 11:03:26AM -0400, Ed Phillips wrote:
> > But the child processes don't have the _same_ file descriptors open, do
> > they?  I thought they had a pipe(s) back to the sshd for protocol
> > encoding/decoding.  Regardless, all the children need to exit _before_
> > sshd exits, and when they do, all of the file descriptors will be closed.
> > When sshd exits, there should be no open file descriptors, right?  (And if
> > sshd exits when there is a process that has a file descriptor open that is
> > a "connection" back to the ssh client, then that's a bug, right?) Am I
> > missing some key point here?  It seems simple... ;-)
>
> We are talking different issues here.
> * sshd daemonizes on startup. In this case it forks and the child process
>   (to become the actual server) closes its fds for stdin, stdout, stderr.
> * When a new connection comes in, a sshd child process is created, that
>   itself will fork()/exec() the user process, normally a shell.
>   There are file descriptors for the network connection (channel) and for the
>   user process. Typically the 3 default file descriptors for stdin, stdout,
>   stderr are open between sshd and user process, but there may be more
>   open files when X11 connections or port forwarding is used.
> * When the user process dies, it closes all of its file descriptors.
>   sshd notes this closure and also closes all file descriptors. On the
>   network side the connection is however not simply closed, but a
>   handshake specified in the SSH protocol is performed to have the
>   encrypted _channel_ closed down before the underlying network
>   connection is closed. Then sshd can exit().

Okay... that makes sense.

>   The often experienced "hang on exit()" problem is caused by processes
>   started from the main user process. If at shell level a process is
>   started with, say "sleep 20000 &", the sleep process may not close
>   its file descriptors (stdin, stdout, stderr), which are identical to
>   the shell's descriptors. Even when the shell now exits, sleep keeps the
>   file descriptors open and therefore the handling sshd process thinks,
>   that data may still be exchanged and does not shut down.
>   (Of course, sleep won't exchange data, but there may be other more important
>   processes be backgrounded.)

The problem I see is that there _are_ no background processes and no file
descriptors left open (there aren't even any processes running on the sshd
side)... but still, ssh hangs on the client side - even though there are
no sockets left on the server side.  Maybe this is a problem with the
protocol implementation in v2.9p2, or maybe it's a problem where ssh
doesn't "know" that the file descriptors are gone (TCP sockets without
keep-alive, client doesn't realize that the count of valid file
descriptors is < 1, etc.).

Hopefully, I'll be able to tell if this is fixed in v2.9.9p2... sometime
today...

Thanks,

	Ed

Ed Phillips <ed at udel.edu> University of Delaware (302) 831-6082
Systems Programmer III, Network and Systems Services
finger -l ed at polycut.nss.udel.edu for PGP public key




More information about the openssh-unix-dev mailing list