Re: Half-closed connections eat 100% cpu

From: Henrik Nordstrom <hno@dont-contact.us>
Date: Thu, 05 Jul 2001 19:14:07 +0200

Andres Kroonmaa wrote:

> When I get enough time I'll go to educate myself what the half-closed
> connections are and why we need them. For now I cannot suggest any
> better fix, but only suggest that in squid.conf we'd default to
> "half_closed_clients off".

"half closed" is when the connection is only closed in one direction.
TCP maintains state in both directions, and each is closed individually
by the sending end for that direction.

TCP sequence

A: SYN (I want to open a connection)
B: SYN,ACK (I accept your open, and want to open one of my own)
A: ACK (Your return connection is accepted)
A: DATA,ACK
B: ACK
...
[now assume A wants to close]
A: FIN,ACK
B: ACK
[at this point, B can still send data to A]
B: DATA,ACK
A: ACK
...
[and finally B is also finished]
B: FIN,ACK
A: ACK
[as FIN has been ACK:ed in both directions the connection is now gone]

If A had done a full close instead of a "half close" above, then B's
attempt to send data to A would have resulted in A sending a RST back,
immediately terminating the connection.

The only statement there is is on this in the HTTP specifications is in
section 8.1.4

   When a client or server wishes to time-out it SHOULD issue a graceful
   close on the transport connection. Clients and servers SHOULD both
   constantly watch for the other side of the transport close, and
   respond to it as appropriate. If a client or server does not detect
   the other side's close promptly it could cause unnecessary resource
   drain on the network.

The term "graceful close" is not defined, but is commonly read to be the
same as the TCP interface definition of CLOSE (i.e. send FIN and
disallow any further transmissions by the application but still allow
receives).

To me this (RFC2616) reads that half closed connections are the same as
aborting the HTTP connection.

Further, there is no means whereby a TCP endpoint can see the difference
between a "half" or "full" close. The packet exchanges are identical.
The only difference is if one tries to send data packets after receiving
a FIN. If it was a half close then the data will get accepted. If it was
a full close then a RESET will be sent back.

Why it is said that the client should issue a graceful close is unclear,
as doing so is quite likely to cause more resource drain than a
immediate close (or even abort) of the connention.

Why a HTTP/1.1 server must be very careful when timing out connections
is well known. Clients are not very happy about receiving "ABORT" (tcp
Reset), and it can seriously mess up things. Almost all TCP
implementations regards "TCP Reset" as a fatal thing, immedately
dropping everything regarding the connection including any received but
not yet processed data, but it is unclear if the above statement is
related to this (does not look that way to me anyway).

The only use (apart from a buggy IBM browser which no longer is in use)
I have found or heard of for half closed connections in HTTP is when
using dummy clients such as telnet or netcat.

(echo "GET http://... HTTP/1.0"; echo ) | telnet proxy 3128

Needless to say, I always disable half_closed_clients. Fixing the above
"client" to behave well is as simple as inserting a sufficient sleep
after the final echo, or better yet use a HTTP client.

--
Henrik
Received on Thu Jul 05 2001 - 11:45:47 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:14:05 MST