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 {
On Sun, 23 Jul 2000, Zack Weinberg wrote:> 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:[snip]> I'd appreciate it if the appended patch could be applied. It causes > ssh to recognize the bug and not emit the error message.Applied - thanks.> [I've reported the bug to the kernel developers but they do not seem > interested in fixing it.]Can you give me a pointer to some discussion on this? -d -- | "Bombay is 250ms from New York in the new world order" - Alan Cox | Damien Miller - http://www.mindrot.org/ | Email: djm at mindrot.org (home) -or- djm at ibs.com.au (work)
hp-ux 10.20 and 11 seem to have a similar issue in that
shutdown(sock, SHUT_RD) return EINVAL when the write side has been
previously closed. you can dup this with:
ssh -R 2300:bar:23 foo
telnet 0 2300
Dec 22 22:04:18 jenny sshd[21722]: error: channel
1: chan_shutdown_read: shutdown() failed for fd13 [i1 o128]: Invalid
argument
regarding the patch below, why do we test for this:
+ || c->ostate == CHAN_OUTPUT_OPEN
+ || c->ostate == CHAN_OUTPUT_WAIT_DRAIN))
vs. just checking for ENOTCONN?
On Sun, 23 Jul 2000, Zack Weinberg wrote:
: 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 {
: