Listener Handoff

Status: planned. Socket activation is not yet implemented. The design below describes the intended behaviour.

The problem

When a server process restarts, there is a window where no one is listening on the port — incoming connections are dropped. For zero-downtime rolling updates, the new process must inherit the listening socket from the old one.

The solution: socket activation

Systemd (or a custom launcher) holds the listening socket fd open. When the process restarts, the new process inherits the fd and can immediately accept connections — the kernel queues them during the gap.

The planned API:

use malkuth::acquire_listener;

// Prefers systemd socket activation (fd inherited), falls back to a plain bind.
let listener = acquire_listener("0.0.0.0:8080").await?;

Enable the socket-activation feature (not yet available):

malkuth = { features = ["socket-activation"] }

How it will work

systemd sets two environment variables:

VariableMeaning
LISTEN_PIDPID of the process that should inherit the fds (must equal ours)
LISTEN_FDSNumber of fds passed (starting at fd 3)

Malkuth will read these, validate LISTEN_PID == our_pid, take ownership of fd 3 (SD_LISTEN_FDS_START), set it to non-blocking, and wrap it in a tokio::net::TcpListener.

If the variables are absent or the PID doesn't match, it falls back to TcpListener::bind(addr).

systemd unit example

# /etc/systemd/system/myapp.socket
[Socket]
ListenStream=8080

[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp.service
[Service]
ExecStart=/usr/bin/myapp

With this setup, systemctl restart myapp does not drop any in-flight connections: the kernel holds them in the listen queue while the new process starts and inherits the fd.