Add systemd socket activation support#3529
Open
drizzt wants to merge 1 commit intovalkey-io:unstablefrom
Open
Conversation
Allows valkey-server to be restarted without causing ECONNREFUSED for
connecting clients. When started under a systemd socket unit, systemd
owns the listening fds and holds them open across service restarts;
valkey inherits them via LISTEN_FDS and skips its own bind()/listen()
for those listeners.
Detection is automatic. After config load, sd_listen_fds() is consulted
and each inherited fd is matched to a configured listener by probing:
- AF_UNIX fds are matched against server.unixsocket by sun_path.
- AF_INET/6 fds have their local address and port extracted via
anetFdToString() and matched against server.port, server.tls_port,
or the cluster bus port (server.cluster_port, falling back to
server.port + CLUSTER_PORT_INCR), and against server.bindaddr[]
with the Valkey wildcards `*` (any IPv4) and `::*` (any IPv6).
An fd whose address/port does not match any configured listener is
closed with a warning, so a `.socket` unit that exposes a broader
address than valkey.conf authorizes will not silently widen exposure.
Listeners with no matching inherited fd fall through to normal
bind()/listen(), so partial activation (e.g. unix-only) works. An
inherited unix socket is never unlinked on shutdown since systemd owns
the path.
Runtime reconfiguration via CONFIG SET port / bind / tls-port is
refused on an inherited listener: closing and re-binding would
relinquish the fd that systemd still tracks and the subsequent bind()
can fail or race. A clear log message asks the operator to adjust the
.socket unit instead.
Build integration:
- Make: no change; USE_SYSTEMD already detects libsystemd and defines
HAVE_LIBSYSTEMD.
- CMake: add matching pkg-config detection of libsystemd, enabling
HAVE_LIBSYSTEMD and sd_notify parity with the Make build.
USE_SYSTEMD=yes is honored as a hard requirement (fatal if
pkg-config or libsystemd is missing), matching the Make build.
The sample utils/systemd-valkey_server.service is documented with
usage instructions and a companion utils/systemd-valkey_server.socket
unit is provided.
Tests in tests/unit/socket-activation.tcl use systemd-socket-activate
(systemd >= 258, with --now) to simulate activation and verify that
the server adopts TCP and unix inherited fds, that a mismatched bind
address is rejected rather than adopted, that the unix socket path is
preserved on shutdown, that CONFIG SET port is refused on an inherited
listener, and that self-binding is unaffected when no fds are
inherited. They skip cleanly when the helper or libsystemd is not
available.
Signed-off-by: Timothy Redaelli <tredaelli@redhat.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Restarting
valkey-servercloses its listening sockets, so clients thatconnect during the restart window see
ECONNREFUSEDinstead of a briefdelay. With systemd socket activation, systemd owns the listening fds
and holds them open across service restarts, so in-flight connections
simply wait in the kernel backlog while the new process starts up.
Fix
When started under a systemd
.socketunit, valkey inherits thelistening fds via
LISTEN_FDSand skips its ownbind()/listen()for those listeners.
Detection is automatic. After config load,
sd_listen_fds()isconsulted and each inherited fd is matched to a configured listener by
probing:
AF_UNIXfds are matched againstserver.unixsocketbysun_path.AF_INET/AF_INET6fds have their local address and port extracted viaanetFdToString()and matched againstserver.port,server.tls_port,or the cluster bus port (
server.cluster_port, falling back toserver.port + CLUSTER_PORT_INCR), and againstserver.bindaddr[]with the Valkey wildcards
*(any IPv4) and::*(any IPv6).An fd whose address/port does not match any configured listener is
closed with a warning, so a
.socketunit that exposes a broaderaddress than
valkey.confauthorizes will not silently widen exposure.Listeners with no matching inherited fd fall through to normal
bind()/listen(), so partial activation (e.g. unix-only) works. Aninherited unix socket is never unlinked on shutdown since systemd owns
the path.
Runtime reconfiguration via
CONFIG SET port/bind/tls-portisrefused on an inherited listener: closing and re-binding would
relinquish the fd that systemd still tracks and the subsequent
bind()can fail or race. A clear log message asks the operator to adjust the
.socketunit instead.Build integration
USE_SYSTEMDalready detects libsystemd anddefines
HAVE_LIBSYSTEMD.HAVE_LIBSYSTEMDandsd_notifyparity with the Make build.USE_SYSTEMD=yesis honored as a hard requirement (fatal ifpkg-config or libsystemd is missing), matching the Make build.
The sample
utils/systemd-valkey_server.serviceis documented withusage instructions and a companion
utils/systemd-valkey_server.socketunit is provided.
Testing
New tests in
tests/unit/socket-activation.tclusesystemd-socket-activate(systemd >= 258, with
--now) to simulate activation and verify:CONFIG SET portis refused on an inherited listener.The tests skip cleanly when
systemd-socket-activateor libsystemd isnot available.