]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Full re-working of the way AcceptFD are handled in Squid
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 12 Jan 2010 06:44:41 +0000 (19:44 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 12 Jan 2010 06:44:41 +0000 (19:44 +1300)
Previously:
  a pre-defined fdc_table was initialized and left waiting just in case
any of the available FD were needed as a listening port. At which point
a handler was assigned and select was setup. Much action was wasted
initializing the array on startup and shutdown, and various unnecessary
maintenance references in comms every FD closure.

Now:
 one merely opens a socket, defines the AsyncCall handler for the
listening FD and creates a ListenStateData object from the two. When a
listener socket is done with, delete the ListenStateData and the FD gets
closed. Callers are responsible for maintaining a pointer to the
ListenStateData.

ListenStateData silently does all the comm processing for setting up and
watching for new connections. Including whether accept() on a port is
delayed until more FD are available. Then when any accept() is completed
it sends the resulting FD and ConnectionDetails objects to the assigned
callback.

COMM_ERR_CLOSING and re-scheduling themselves is now not generally relevant
to layers higher than comm on listening sockets. The callbacks never get
called at all unless a real new connection has been accepted. The old code
is still used internally by the comm layer, but details of error handling
and re-scheduling of accept() never leak out into higher level code now.

ListenStateData can be created in use-once or accept-many form.
* use-once are intended for short temporary listening sockets such as
  FTP passive data links. A single inbound connection is allowed after
  which the handler self-destructs.
* accept-many are for long term FD such as the http_port listeners which
  continuously accept new connections and pass them all to the same handler
  until something causes the ListenStateData to die (deletion, or self
  destruct under fatal socket IO errors).

The previous existing AcceptLimiter is slightly remodeled to work with
ListenStateData* instead of an intermediary callback reference type.
And also altered from LIFO to FIFO behavior for better client response
times under load.

All the code relevant to comm layer processing of accept() is bundled
into libcomm-listener.la.

TODO:
* wrap the SSL handshake into ListenStateData. That way SSL on some
  sockets can be treated as a real transport layer and for example
  httpsAccept and httpAccept merged into one function.

* there is one bug uncovered, that when the accept() handler is deleted
  and the port closed while it has been deferred. The deferred queue
  needs to be cleared of all (multiple) deferral events, or they will
  be scheduled uselessly and may segfault with FD errors.
  This only gets hit if Squid is shutdown during active load limiting.


Trivial merge