Skip to content

try fixing deadlock in xds when more than 65 services on the same port. - #2777

Open
aryehlev wants to merge 3 commits into
grpc:masterfrom
aryehlev:fix-deadlock
Open

try fixing deadlock in xds when more than 65 services on the same port.#2777
aryehlev wants to merge 3 commits into
grpc:masterfrom
aryehlev:fix-deadlock

Conversation

@aryehlev

@aryehlev aryehlev commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

we have in our environment alot of versions of services all on the same port, this causes a deadlock in our xDS client at startup.
The shared route config for the port references more clusters than the client's internal queue can hold (64), and the two tasks that need each other to drain it end up waiting on each other.

@YutaoMa

YutaoMa commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

@aryehlev , thanks for the PR! It's indeed a crucial bug and exactly the kind of report we appreciate seeing from real production usage. The solution makes sense to me, especially that it matches the dispatching design of other grpc implementations mostly. I added two comments above.

Comment thread tonic-xds/src/xds/resource_manager.rs Outdated
struct ManyClustersServer;

#[tonic::async_trait]
impl AggregatedDiscoveryService for ManyClustersServer {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be better to reuse the existing xds-test-util::XdsTestControlPlaneServic utility we created in-repo recently.


/// Build the in-flight delivery future for one response's staged watcher
/// notifications, or `None` when there is nothing to deliver.
fn dispatch_pending(deliveries: Vec<Delivery>) -> Option<PendingDispatch> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optimization suggestion: instead of sending Vec<Delivery> around, use refcount around one token, i.e. Arc<Option<Oneshot>> in ProcessingDone. I found out all the other grpc implementations use refcounts to track the updates dispatch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im not sure about this one, you mean to avoid this vec in line 833?
let mut done_rxs = Vec::with_capacity(deliveries.len());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the confusion, the comment is specifically about the oneshot channel in ProcessingDone. dispatch_resources need to do N(resources) * W(watchers) oneshot chanel allocations for each response. This is a pre-existing issue with the ProcessingDone design, not introduced by this PR. I recommend refactor ProcessingDone to use one Arc to track a single response now to both eliminate the allocations as well as simplifying Delivery shape here, it can drop the Receiver field.

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.

2 participants