The ultimate SO_LINGER page, or: why is my tcp not reliable (2009)

April 14, 2026
Detailed view of blue ethernet cables with exposed gold-plated conductors.
Photo by Nic Wood on Pexels

It has been reported that a blog post collecting expert advice on an obscure corner of TCP programming has shaken a few assumptions. The author, surprised to learn he didn't fully understand TCP semantics, trawled the web and consulted seasoned implementers — H. Willstrand, Evgeniy Polyakov, Bill Fink, Ilpo Jarvinen and Herbert Xu — promising to write it up so the confusion could be put to rest. The result is a clear, hair-on-fire reminder: "reliable" in TCP doesn't always mean what application developers expect.

What actually goes wrong

Writes to a TCP socket are not the same as writes to disk. A successful write() only means the kernel accepted your data and will try to send it — not that the remote application has seen it. Packets move through adapters and queues, hand-offs all the way, and an ACK only proves the remote kernel got the bytes, not that the remote process read them. So how do you end up losing the final megabytes? Close() can, under some conditions, drop the connection even with unsent or unconsumed data still in flight. The emotional sting here is tangible: you thought everything was sent. You felt safe. Then, poof.

The linger myth and RFC landmines

Everyone points at SO_LINGER as the magic switch. Turn it on, right? Not so fast. Enabling SO_LINGER and rerunning the test still failed to deliver all bytes in some cases. Why? RFC 1122 warns that a CLOSE with pending readable data may lead to an immediate RST — the peer resets instead of politely finishing the transfer. In short: socket options, kernel behavior, NIC queues and standards all conspire. Allegedly, even carefully set linger options won't save you in every implementation or scenario.

The practical takeaway is simple and sober: don't treat close() as a transactional commit. If you really need delivery confirmation, design for it — use application-level acknowledgements, shutdown(SHUT_WR) and wait for the other side's EOF, or explicitly coordinate protocol-level handshakes. This write-up is a must-read for anyone who ever shrugged and trusted TCP to “just work.” Because sometimes, it won’t — and that’s the moment you learn the difference between theory and the messy reality of networks.

Sources: blog.netherlabs.nl, Lobsters