From 75719beea3ed4df9875443e38d617b2d43d1cf72 Mon Sep 17 00:00:00 2001 From: Kannan J Date: Tue, 5 Nov 2024 09:40:20 +0000 Subject: [PATCH] Fix NameResolvers calling Listener2.onResult2 outside of the synchronization context to call it from inside of the synchronization context. Fixes #11662. --- api/src/main/java/io/grpc/NameResolver.java | 6 ++++-- .../grpc/internal/ManagedChannelImplBuilder.java | 15 ++++++++------- .../main/java/io/grpc/netty/UdsNameResolver.java | 5 ++++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/api/src/main/java/io/grpc/NameResolver.java b/api/src/main/java/io/grpc/NameResolver.java index b9590ab5d5a..a1dea016377 100644 --- a/api/src/main/java/io/grpc/NameResolver.java +++ b/api/src/main/java/io/grpc/NameResolver.java @@ -219,13 +219,15 @@ public abstract static class Listener2 implements Listener { @Override @Deprecated @InlineMe( - replacement = "this.onResult2(ResolutionResult.newBuilder().setAddressesOrError(" + replacement = "this.onResult(ResolutionResult.newBuilder().setAddressesOrError(" + "StatusOr.fromValue(servers)).setAttributes(attributes).build())", imports = {"io.grpc.NameResolver.ResolutionResult", "io.grpc.StatusOr"}) public final void onAddresses( List servers, @ResolutionResultAttr Attributes attributes) { // TODO(jihuncho) need to promote Listener2 if we want to use ConfigOrError - onResult2( + // Calling onResult and not onResult2 because onResult2 can only be called from a + // synchronization context. + onResult( ResolutionResult.newBuilder().setAddressesOrError( StatusOr.fromValue(servers)).setAttributes(attributes).build()); } diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java index 48a255472e1..1fe403548a0 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java @@ -878,13 +878,14 @@ public String getServiceAuthority() { @Override public void start(Listener2 listener) { - listener.onResult2( - ResolutionResult.newBuilder() - .setAddressesOrError( - StatusOr.fromValue( - Collections.singletonList(new EquivalentAddressGroup(address)))) - .setAttributes(Attributes.EMPTY) - .build()); + args.getSynchronizationContext().execute(() -> + listener.onResult2( + ResolutionResult.newBuilder() + .setAddressesOrError( + StatusOr.fromValue( + Collections.singletonList(new EquivalentAddressGroup(address)))) + .setAttributes(Attributes.EMPTY) + .build())); } @Override diff --git a/netty/src/main/java/io/grpc/netty/UdsNameResolver.java b/netty/src/main/java/io/grpc/netty/UdsNameResolver.java index de14dc8b460..437db5cce82 100644 --- a/netty/src/main/java/io/grpc/netty/UdsNameResolver.java +++ b/netty/src/main/java/io/grpc/netty/UdsNameResolver.java @@ -30,10 +30,12 @@ final class UdsNameResolver extends NameResolver { private NameResolver.Listener2 listener; private final String authority; + private final Args args; UdsNameResolver(String authority, String targetPath, Args args) { checkArgument(authority == null, "non-null authority not supported"); this.authority = targetPath; + this.args = args; } @Override @@ -58,7 +60,8 @@ private void resolve() { List servers = new ArrayList<>(1); servers.add(new EquivalentAddressGroup(new DomainSocketAddress(authority))); resolutionResultBuilder.setAddressesOrError(StatusOr.fromValue(servers)); - listener.onResult2(resolutionResultBuilder.build()); + args.getSynchronizationContext().execute(() -> + listener.onResult2(resolutionResultBuilder.build())); } @Override