Work around Linux kernel bug provoked by nchan.c
Zack Weinberg
zack at wolery.cumb.org
Mon Jul 24 03:03:23 EST 2000
The Linux implementation of TCP sockets has a bug which causes
shutdown(sock, SHUT_RD) to fail spuriously (ENOTCONN) if the write
side of the socket has already been shut down. If you are using SSH
port forwarding to tunnel HTTP through a firewall, nchan.c will tickle
this bug once for every HTTP exchange. You will therefore get lots of
useless, annoying error messages:
channel 2: chan_shutdown_read: shutdown() failed for fd7 [i1 o128]: Transport endpoint is not connected
Here's a complete debugging trace of one such forwarded channel. This
is SSH1 protocol; I haven't got the setup to do SSH2 yet. The remote
server is 2.0.12 F-SECURE SSH on Solaris 2.6; I am using openssh
2.1.1p4 with kernel 2.2.16.
debug: channel 2: new [listen port 3128 for webcache.example.com port 3128, connect from localhost port 1817]
debug: channel 2: rcvd ieof
debug: channel 2: output open -> drain
debug: channel 2: obuf empty
debug: channel 2: output drain -> closed
debug: channel 2: send oclose
debug: channel 2: close_write
debug: channel 2: read<=0 rfd 7 len 0
debug: channel 2: read failed
debug: channel 2: input open -> drain
debug: channel 2: close_read
channel 2: chan_shutdown_read: shutdown() failed for fd7 [i1 o128]: Transport endpoint is not connected
debug: channel 2: input: no drain shortcut
debug: channel 2: ibuf empty
debug: channel 2: input drain -> wait_oclose
debug: channel 2: send ieof
debug: channel 2: rcvd oclose
debug: channel 2: input wait_oclose -> closed
debug: channel 2: full closed
I'd appreciate it if the appended patch could be applied. It causes
ssh to recognize the bug and not emit the error message.
[I've reported the bug to the kernel developers but they do not seem
interested in fixing it.]
zw
--- openssh-2.1.1p4.orig/nchan.c Thu Jun 22 04:32:31 2000
+++ openssh-2.1.1p4/nchan.c Sun Jul 23 09:42:23 2000
@@ -483,7 +483,12 @@
return;
debug("channel %d: close_read", c->self);
if (c->sock != -1) {
- if (shutdown(c->sock, SHUT_RD) < 0)
+ /* shutdown(sock, SHUT_READ) may return ENOTCONN if the
+ write side has been closed already. */
+ if (shutdown(c->sock, SHUT_RD) < 0
+ && (errno != ENOTCONN
+ || c->ostate == CHAN_OUTPUT_OPEN
+ || c->ostate == CHAN_OUTPUT_WAIT_DRAIN))
error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
c->self, c->sock, c->istate, c->ostate, strerror(errno));
} else {
More information about the openssh-unix-dev
mailing list