The meaning of listen(2)'s backlog parameter

February 20, 2013

I was all set to write an entry where I was going to mention in passing something about the effects of listen(2)'s backlog parameter. Then I made the mistake of actually testing things to see if I understood things correctly. Now I am writing a different entry.

If you read your typical Unix manpage for listen(), it will say something like:

The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow.

Ha ha. As if. In practice the only portable assumption that you can make is that the backlog sets the minimum number of connections that may be pending, where the minimal definition of 'pending' is 'the other side has called connect() and you have not yet called accept()'. The actual observed backlog that can build up depends on the specific Unix version you are using and on at least some Unix versions, on the specific type of sockets involved (on Linux, Unix domain sockets behave quite differently from TCP IPv4 sockets). What happens when there are too many pending connections is also system and perhaps socket type dependent.

'Pending' may also have various different definitions. The minimal one is 'the other side has had connect() succeed', ie the kernel has successfully accepted and established the connection on your behalf (cf); it's just waiting for you to get around to call accept(). For TCP connections, incomplete TCP connections (ones that have not completed the three-way handshake) are not counted against this limit on basically any modern Unix. However, your kernel may not complete the three-way handshake if doing so would make the pending queue too high.

(In the distant early days of the modern Internet, Unixes did count incomplete TCP connections against socket backlog limits (for good reasons at the time). Then people discovered that SYN flooding was a great way to DoS servers that they didn't like. Nowadays any serious Unix has much better protections against SYN floods that don't chew up resources and so don't need limits.)

Note that most Unixes silently impose a maximum value on the backlog value. Some impose a minimum as well, and some impose different minimums depending on what the socket protocol is.

This leads to the obvious question: what should you set the backlog value to when you call listen()? My current view is that setting it low doesn't reliably do anything so you probably should set it high. Given that the kernel will clamp the value if you go too high I suggest going for at least 128 or 256, maybe more; going high in your software means that the actual number is up to whatever limit the local system has set.

(There is an important consequence of setting it high, but that's the entry I was originally planning to write before I made the mistake of checking reality.)

By the way, all of the system and socket type dependent behavior of listen()'s backlog means that you should never trust tuning advice about what you should set it to from anyone who doesn't specify their Unix, the specific version of their Unix, and the specific socket types involved. If someone says 'oh, you want to set it to 64' without giving you that information (and without any other explanation), you can ignore them. Possibly this means you should ignore me too.

Written on 20 February 2013.
« The source of C's dependency hell for linking
Some notes on my first experience with Go »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Feb 20 01:22:05 2013
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.