IETF-SSH archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Channel close logic, needs clarification?



Do we need to make some more detailed recommendations about channel
close logic? Different behaviour can cause interoperability problems.

For instance, I have heard reports that when logging in with the
openssh client to a recent lshd, the client will hang after logout.
I'll describe the logic that lsh and lshd uses. The basic rules are as
follows:

1. When SSH_MSG_CHANNEL_CLOSE is both sent and received, the channel
   is killed. This is unconditionally required by the spec.

2. When SSH_MSG_CHANNEL_EOF is both sent and received,
   SSH_MSG_CHANNEL_CLOSE is sent (unless it wasn't sent earlier). This
   makes sense in almost all cases (and the only exceptions I'm aware
   of seem out-of-scope here, they are related to proxying or
   gatewaying channels).

So, what is left to decide is when to send SSH_MSG_CHANNEL_EOF. In
most cases, the decision is easy, but sometimes it is not.

Consider the scenario where a client creates a session channel, gets a
login shell, and later exits the shell by explicitly typing exit or
logout. The result, at the server side, is

 * The server handles SIGCLD, discovers that its child process died,
   and sends an SSH_MSG_CHANNEL_REQUEST "exit-status". This is of
   course not done directly by the signal handler, but some time later
   from the main loop.

 * The server gets an EOF condition on the process' stdout and stderr
   (unless their are any grand children that still has one or the other
   open). When EOF has occured on both stdout and stderr, the server
   sends an SSH_MSG_CHANNEL_EOF.

The two events above can occur in more or less random order. The
server has not received any SSH_MSG_CHANNEL_EOF, so rule 2 doesn't
apply. The channel is still open.

What happens at the client? When the lsh client receives
an SSH_MSG_CHANNEL_REQUEST "exit-status" message, it decides that it's
time to stop talking, and it sends an SSH_MSG_CHANNEL_EOF. Now rule 2
applies, and the channel gets closed properly.

It's not obvious that the channel should be closed at this time; there
may be some grand child process that is still alive. If the client has
received a SSH_MSG_CHANNEL_EOF that implies that no process has its
*output* connected to the channel, but even in this case (which lsh
doesn't try to look for), there may be some process with input still
connected to the channel. And this is why the server doesn't close the
channel automatically at process death; the user may still have some
processes alive to talk to, and the client is more likely than the
server to know what the user really wants.

But appearantly, this logic doesn't work right when talking to the
openssh client. It doesn't send any SSH_MSG_CHANNEL_EOF, and to the
user it appears that the system just hangs.

Does the lsh behaviour above make sense to you? What are other
implementations doing?

Regards,
/Niels



Home | Main Index | Thread Index | Old Index