sshd gets stuck: select() in packet_read_seqnr waits indefinitely
Darren Tucker
dtucker at zip.com.au
Thu Mar 15 13:43:47 EST 2007
On Wed, Mar 14, 2007 at 07:12:09PM -0600, Matt Day wrote:
> On Thu, Mar 15, 2007 at 11:14:16AM +1100, Darren Tucker wrote:
> > You could try the attached patch.
>
> Oh, cool...thanks for the fast response!
>
> I have a question about the patch. With it applied, packet_read_seqnr
> now reads:
>
> /* Wait for some data to arrive. */
> while (select(connection_in + 1, setp, NULL, NULL,
> packet_wait_tvp) == -1 &&
> (errno == EAGAIN || errno == EINTR))
> ;
>
> /* Read data from the socket. */
> len = read(connection_in, buf, sizeof(buf));
> ...
> On FreeBSD, select() will return 0 upon timeout, so packet_read_seqnr
> would end up calling read() even though the descriptor isn't ready,
> so I think it would block.
The descriptor is O_NONBLOCK (set by packet_set_nonblocking()), so the
read() should return -1 with errno == EWOULDBLOCK or EAGAIN.
> Similarly, I don't see how a select() timeout would cause packet_write_wait
> to abort. Instead it would call packet_write_poll (which calls write())
> even though the descriptor isn't ready for writing. Am I missing something?
The next couple of lines after the ones you quoted are:
if (len == 0) {
logit("Connection closed by %.200s", get_remote_ipaddr());
cleanup_exit(255);
}
if (len < 0)
fatal("Read from socket failed: %.100s", strerror(errno));
len should be -1 in the case of a timeout, so that should kill the
connection (I've not tested it).
You could test for EWOULDBLOCK or EAGAIN and provide a more informative
error message, though.
--
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69
Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.
More information about the openssh-unix-dev
mailing list