Skip to content

services: report bound listener addresses - #991

Open
torinnd wants to merge 2 commits into
cloudflare:mainfrom
torinnd:report-bound-listeners-stacked
Open

services: report bound listener addresses#991
torinnd wants to merge 2 commits into
cloudflare:mainfrom
torinnd:report-bound-listeners-stacked

Conversation

@torinnd

@torinnd torinnd commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #988.

Today there is no way to learn the actual address of a listener bound to port 0 while Server owns the listening fds. Tests and embedders that want an OS-assigned port have to either give up graceful upgrade and bind the socket themselves, or poll.

This PR adds Service::watch_bound_addresses(), a tokio::sync::watch receiver. The service publishes every bound TCP and Unix address once, in endpoint insertion order, after all of its listeners bind and before any accept loop starts. Callers subscribe before moving the service into Server. If startup fails, the watch closes without a value.

To support this, ListenerEndpoint::local_addr and TransportStack::local_addr are now crate-visible (they were #[cfg(test)]) and return the L4 SocketAddr so Unix listeners are covered too. No changes to the accept path.

Tests start a full Server with a port-0 listener and connect through the published address, and run two services with the same 127.0.0.1:0 configuration and distinct transfer IDs to check they publish different ports and route correctly.

(This is a two-commit PR, following #990. If #990 merges first, this PR rebases down to the second commit only.)

Add ListenerConfig::fd_transfer_id so listeners sharing a configured address, including repeated port-zero and SO_REUSEPORT listeners, use distinct fd-table keys and retain their sockets across same-version graceful upgrades. Fixed TCP, Unix, and unidentified listeners retain their existing keys.

Validate IDs during listener construction and return BindError for empty, whitespace-containing, or duplicate IDs. Track keys registered by the current process so an unidentified duplicate address is a bind error rather than a second owner of the same raw fd; no upstream test or example relies on that sharing.

Mixed-version upgrades may rebind identified listeners because old binaries do not understand the new keys. Tests cover build-time validation, distinct routing, duplicate IDs, legacy keys, and a real SCM_RIGHTS round trip.
Allow callers to subscribe to the actual addresses of a listening service before moving it into Server. The service publishes every bound TCP or Unix address after all listeners bind and before accept loops start. This makes full-server tests with port 0 race-free while Pingora retains ownership of listening fds.

TCP port-0 listeners can use stable transfer IDs from the parent change to remain distinct and retain their ports across new-to-new graceful upgrades. The transfer-ID API documents that explicitly identified listeners may rebind during a mixed-version upgrade or rollback.

Tests connect through published addresses and run two services with the same 127.0.0.1:0 configuration and distinct transfer IDs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report actual listener addresses after binding

1 participant