Repository navigation
fix(ldk-node): reap finished connection tasks and cap concurrent inbound connections - #545
Merged
Merged
Conversation
…und connections Cancellable runtime tasks were kept in a JoinSet that was only drained at shutdown, so every finished inbound connection task stayed tracked for the node's lifetime. Track them with tokio-util's TaskTracker and a CancellationToken instead, as upstream ldk-node does after 0.7.1: a task is released when it ends, and stop still cancels and waits for every live task. Move the inbound accept loop into its own module and handle at most MAX_CONCURRENT_INBOUND_CONNECTIONS (512) accepted connections at a time; a socket accepted beyond that is closed at once. Established and outbound connections are unaffected. A failed accept is logged and retried instead of ending the listener. Tests run 200 short loopback connections and check that only the accept loop remains tracked, that excess sockets are closed while open ones stay up and freed slots are reused, and that stop closes open connections.
Stop used to swap in a fresh task set before cancelling the old one, so a task spawned while the stop was in progress (or after it) landed in the new set and could outlive the stop. As upstream ldk-node does, stop now closes the tracker in place and a closed tracker refuses new cancellable tasks; Node::start opens a fresh set, so restart still works. Add a regression where a running task spawns a child after the stop has begun: the child is never polled and nothing stays tracked. The inbound test fixture now stops its tasks before dropping the runtime, so the runtime is never dropped on one of its own workers. Patch notes describe what stop covers and the inbound limit's behaviour while saturated.
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.
Summary
JoinSetthat was only drained at shutdown. Every finished inbound connection task therefore stayed tracked until the node stopped. Cancellable tasks are now tracked withtokio_util::task::TaskTrackerand aCancellationToken, so a task is released when it ends. This follows upstream ldk-node's "Release completed cancellable tasks" (Release completed cancellable tasks lightningdevkit/ldk-node#997). That change landed onmainafter 0.7.1 and is not in a release yet.Node::startopens a fresh set, so restart still works.lightning_net_tokio::setup_inbound, is not tracked, as before. That task ends whenNode::stopdisconnects all peers.inbound.rs. At mostMAX_CONCURRENT_INBOUND_CONNECTIONS(512) accepted connections are handled at a time across all listening addresses. A socket accepted beyond that is closed at once.acceptis logged and retried after 100 ms. A failed socket conversion ends only that connection.tokio-util(rtfeature) is added to the vendored manifest. It is already in the root lock at 0.7.18, and the vendor lock pins the same version.BITSOV-PATCH.mddocuments the delta.Tests
inbound::tests::finished_inbound_connection_tasks_are_released: 200 connect/close cycles on an ephemeral loopback port. On the previous runtime, 201 tasks stayed tracked (200 finished connections plus the accept loop). Now only the accept loop remains.inbound::tests::connections_beyond_the_limit_are_closed_and_slots_are_reused: with 4 slots, a 5th socket is closed, the 4 open ones stay up, and a freed slot is reused.inbound::tests::stopping_cancels_open_inbound_connectionsruntime::tests::task_spawned_while_stopping_does_not_outlive_the_stop: a running task spawns a child after the stop has begun. The child is never polled and nothing stays tracked after the stop. With the previous fresh-set behaviour, one task stayed tracked.runtime::tests: finished tasks are released; stop and drop cancel live tasks; a task spawned after a stop is refused; spawning works again after a restart.--nocaptureoutput is clean.