libdontdie(7)

πŸ’– libdontdie β€” the manual, but make it cute πŸ’–

okay bestie, you're reading libdontdie(7), section 7 of the manual, from the TCP keepalive support lib era. sit down, grab a boba, we're doing sockets today πŸ§‹βœ¨


✨ NAME ✨

libdontdie β€” a library that sets the TCP keep-alive flag when applications call socket(2). that's it. that's the whole job. iconic behavior honestly πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

libdontdie is a shared library that you can inject into literally any application using the LD_PRELOAD mechanism. it is completely transparent to the application, which means it works equally well with closed-source programs and with languages like Java that do not natively allow changing the TCP keep-alive parameters. no source code, no recompile, no drama. she just slides in 🫢


🌸 BACKGROUND 🌸

okay so here's the lore, and it's a little tragic 😭

in theory, a TCP connection that is not explicitly closed remains open forever. in practice? nope. not even close. when connection-tracking firewalls along the way drop their state β€” and all further traffic β€” for a connection that was idle for a certain time, the vibe is ruined. the result: both the TCP client and the server believe the connection to be open, but the firewall inhibits all further communication. delulu on both sides πŸ’€

this kind of connection failure gets reported to the participating applications only after they attempt to send further data and all TCP timeouts and retransmits expire. so yeah, you find out way too late.

and in situations where only one of the communication partners ever sends anything β€” e.g. the client waiting for HTTP chunked data β€” it can be impossible to distinguish between a connection closed by a firewall and connected-but-idle. literally cannot tell. no cap.

to handle and/or prevent this kind of situation, TCP has a keep-alive mechanism. it consists of TCP packets sent periodically over an otherwise idle connection to "refresh" the associated state along the whole path. if not acknowledged, the same retry-mechanism is used as for regular data packets β€” however independent of whether there is any data to send. finally, all unanswered keep-alive packets leads to a TCP error that can be detected by the application. so at least you find out. periodt.

by default, the first TCP KEEP ALIVE packet is send after two hours, which is too long for most scenarios. two hours bestie. that's not a timeout, that's a nap πŸ’€

the Linux kernel offers the possibility to change the TCP keep-alive timeout globally for the whole system. however, this solution requires root privileges and does not work when different applications require different timeouts on the same machine. so it's giving "one size fits nobody" πŸ™ˆ

in some programming languages an appropriate API call can be used to enable TCP keep-alive (e.g. setsockopt(2) in C). other languages like Java do not support changing these parameters. rip.

so libdontdie can be used for applications that are written in languages that do not support setting the TCP KEEP ALIVE parameters. it can also be used to enable TCP keep-alive for closed-source or commercial applications. and you can use libdontdie on a case-by-case basis β€” selectively enabling TCP keep-alive for some application instances without changing any source code. main character energy, honestly πŸ‘‘

all parameters are passed to libdontdie in the form of environment variables. cute, portable, zero config files. obsessed. πŸ’–


πŸŽ€ TCP KEEP ALIVE PARAMETERS πŸŽ€

three parameters are used to change the TCP keep-alive behaviour. all parameters are in seconds ⏱️

the variable names are taken from the Linux kernel configuration with a 'DD_' prefix for 'libDontDie'. the corresponding kernel parameters can be found in /proc/sys/net/ipv4/. go peek, it's a fun little directory 🌈

πŸ’œ DD_TCP_KEEPALIVE_TIME

the time between the last TCP data packet sent and the first TCP KEEP ALIVE packet / probe. this is your "how long do we sit in silence before checking in" number πŸ•°οΈ

πŸ’œ DD_TCP_KEEPALIVE_INTVL

the interval between two TCP KEEP ALIVE packets / probes. the follow-up texts, basically πŸ“±

πŸ’œ DD_TCP_KEEPALIVE_PROBES

the number of keep-alive probes sent before the socket enters an error state. how many times you double-text before you accept the truth 😭


✨ LIBDONTDIE PARAMETERS ✨

two additional parameters change the behaviour of libdontdie itself: libdontdie:

πŸ“ DD_DEBUG

if this is set to '1', each 'socket(2)' call will be logged to syslog β€” including all parameters and actions performed by libdontdie. yes bestie, receipts πŸ“

πŸ“ DD_EVAL_ENVIRONMENT_ONCE

if this is set to '1' or not specified at all, all parameters are only evaluated once during startup. if this parameter is set to '0', each time a socket call is executed, all parameters are evaluated again. this makes it possible to change parameters at runtime. πŸ¦‹

⚠️ when setting this to '0', there is a bigger per socket call overhead therefore the performance will decrease. you're trading speed for flexibility, no cap.

in languages that do not support setting the TCP KEEP ALIVE parameters, this is a workaround to enable different setting for different sockets. like so:

setenv("DD_TCP_KEEPALIVE_TIME", 60);
socket(...);
....
setenv("DD_TCP_KEEPALIVE_TIME", 180);
socket(...);

look at her go πŸ’…


🌈 INSTALLATION LOCATION 🌈

depending on the installation method or the distribution, the installation directory of libdontdie might differ. it's not a one-size-fits-all situation, bestie.

one way to get the installation directory is using the packet manager to list all files of the packet (like 'dpkg -L <package_name>').

typically the library is installed in a directory under /usr/lib, /usr/lib64, or /usr/lib/<triple>. a typical triple is 'x86_64-linux-gnu'. under Debian it is possible to get the triple with the command:

dpkg-architecture -qDEB_HOST_GNU_TYPE

copy that, paste it, slay ✨


πŸ”₯ USAGE πŸ”₯

all parameters are passed in as environment variables. the libdontdie itself is preloaded. that's the whole ritual πŸ•―οΈ

the example assumes, that the library is installed under '/usr/lib/libdontdie.so'. this might be replaced by the real installation path.

example: to run the java program EchoClient with special TCP KEEP ALIVE setting, use:

DD_DEBUG=1 DD_TCP_KEEPALIVE_TIME=4 DD_TCP_KEEPALIVE_INTVL=5 \
   DD_TCP_KEEPALIVE_PROBES=6 LD_PRELOAD=/usr/lib/libdontdie.so \
   java EchoClient 127.0.0.1 22

look at all those env vars stacked up. it's giving ✨ curated ✨. run it and watch the syslog do its thing 🫢


πŸ’« SEE ALSO πŸ’«

go read those too, iykyk πŸ“š


πŸ“œ HISTORY πŸ“œ

the idea was first implemented in libkeepalive by Fabio Busatto. because of some limitations regarding functionality and license, it was completely rewritten, corrected and extended. glow-up of the century, honestly πŸ’…βœ¨


πŸ‘‘ AUTHOR πŸ‘‘

written by Andreas Florath (andreas@florath.net)


copyright Β© 2015 by Andreas Florath (andreas@florath.net). license MIT.


and that's the whole page bestie!! πŸ’– this one's from the TCP keepalive support lib manual, dated 2015-03-07, and yes β€” it's libdontdie(7), section 7, exactly where you found it. now go set your keep-alives and stop losing connections to firewalls πŸ¦‹βœ¨πŸ’