Feature Request
Crates
tonic (transport server: TcpIncoming / UnixIncoming), behind a new opt-in socket-activation cargo feature. Unix-only.
Motivation
Under systemd, a service can be started on-demand when a client connects. The manager creates and listens on the socket itself, then passes the already-listening file descriptor to the spawned process via the LISTEN_FDS / LISTEN_PID environment variables.
Consider a gRPC server that receives requests only occasionally. Keeping it running around the clock just to answer the rare request wastes memory and other resources. A better fit for that situation is to let the process run only while it is actually serving requests: the service manager (systemd) holds the socket, starts the server on an incoming connection, and the server can stop itself once it goes idle, after which the manager re-activates it on the next connection.
This enables:
- Lazy startup / on-demand activation - the server process only runs when there is actual traffic.
- Zero-downtime restarts - the listening socket outlives the process, so connections established during a restart are not refused.
Today a tonic server always calls bind() itself, so it cannot participate in socket activation.
Proposal
Add an opt-in socket-activation cargo feature (Unix-only). When enabled, TcpIncoming::bind and UnixIncoming::bind first check whether a matching listening descriptor was passed in via LISTEN_FDS / LISTEN_PID`:
- Validate
LISTEN_PID matches the current process id.
- Scan the inherited descriptors (
SD_LISTEN_FDS_START = 3 onward), verifying each is a listening stream socket.
- Match by requested address (TCP, treating IPv4-mapped and wildcard binds as equal) or by socket path (UDS).
- Adopt the matching fd instead of binding a fresh socket; otherwise fall back to the normal
bind().
The feature is off by default, so behavior is unchanged unless explicitly enabled.
Alternatives
Do it in user code - the application reads LISTEN_FDS and constructs a listener, passing it via serve_with_incoming. This works but forces every user to re-implement the sd_listen_fds protocol (pid check, fd scanning, socket-type validation, address matching) correctly. Baking it into the transport makes the common case a one-line, feature-gated opt-in.
libsystemd / sd-listen-fds crate dependency - pulls in an extra (often C-linked) dependency for a small, well-specified protocol. The proposed implementation needs only socket2, which tonic already uses.
Feature Request
Crates
tonic(transport server:TcpIncoming/UnixIncoming), behind a new opt-insocket-activationcargo feature. Unix-only.Motivation
Under systemd, a service can be started on-demand when a client connects. The manager creates and listens on the socket itself, then passes the already-listening file descriptor to the spawned process via the
LISTEN_FDS/LISTEN_PIDenvironment variables.Consider a gRPC server that receives requests only occasionally. Keeping it running around the clock just to answer the rare request wastes memory and other resources. A better fit for that situation is to let the process run only while it is actually serving requests: the service manager (systemd) holds the socket, starts the server on an incoming connection, and the server can stop itself once it goes idle, after which the manager re-activates it on the next connection.
This enables:
Today a tonic server always calls
bind()itself, so it cannot participate in socket activation.Proposal
Add an opt-in
socket-activationcargo feature (Unix-only). When enabled,TcpIncoming::bindandUnixIncoming::bindfirst check whether a matching listening descriptor was passed in viaLISTEN_FDS/ LISTEN_PID`:LISTEN_PIDmatches the current process id.SD_LISTEN_FDS_START = 3onward), verifying each is a listening stream socket.bind().The feature is off by default, so behavior is unchanged unless explicitly enabled.
Alternatives
Do it in user code - the application reads
LISTEN_FDSand constructs a listener, passing it viaserve_with_incoming. This works but forces every user to re-implement thesd_listen_fdsprotocol (pid check, fd scanning, socket-type validation, address matching) correctly. Baking it into the transport makes the common case a one-line, feature-gated opt-in.libsystemd/sd-listen-fdscrate dependency - pulls in an extra (often C-linked) dependency for a small, well-specified protocol. The proposed implementation needs onlysocket2, which tonic already uses.