core: Clear ConfigSelector in panic mode

If the failure is before the NameResolver has returned the first time,
RPCs would be queued waiting for service config. We don't want to use
the ConfigSelector, as we are trying to circumvent the NameResolver and
LoadBalancer.

Fixes #9257
This commit is contained in:
Eric Anderson 2022-06-13 13:55:46 -07:00
parent b06942d63b
commit d2b05380de
2 changed files with 38 additions and 0 deletions

View File

@ -887,6 +887,7 @@ final class ManagedChannelImpl extends ManagedChannel implements
}
updateSubchannelPicker(new PanicSubchannelPicker());
realChannel.updateConfigSelector(null);
channelLogger.log(ChannelLogLevel.ERROR, "PANIC! Entering TRANSIENT_FAILURE");
channelStateManager.gotoState(TRANSIENT_FAILURE);
}
@ -1755,6 +1756,9 @@ final class ManagedChannelImpl extends ManagedChannel implements
@SuppressWarnings("ReferenceEquality")
@Override
public void run() {
if (ManagedChannelImpl.this.nameResolver != resolver) {
return;
}
List<EquivalentAddressGroup> servers = resolutionResult.getAddresses();
channelLogger.log(

View File

@ -2799,6 +2799,40 @@ public class ManagedChannelImplTest {
panicExpected = true;
}
@Test
public void panic_atStart() {
final RuntimeException panicReason = new RuntimeException("Simulated NR exception");
final NameResolver failingResolver = new NameResolver() {
@Override public String getServiceAuthority() {
return "fake-authority";
}
@Override public void start(Listener2 listener) {
throw panicReason;
}
@Override public void shutdown() {}
};
channelBuilder.nameResolverFactory(new NameResolver.Factory() {
@Override public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
return failingResolver;
}
@Override public String getDefaultScheme() {
return "fakescheme";
}
});
createChannel();
// RPCs fail immediately
ClientCall<String, Integer> call =
channel.newCall(method, CallOptions.DEFAULT.withoutWaitForReady());
call.start(mockCallListener, new Metadata());
executor.runDueTasks();
verifyCallListenerClosed(mockCallListener, Status.Code.INTERNAL, panicReason);
panicExpected = true;
}
private void verifyPanicMode(Throwable cause) {
panicExpected = true;
@SuppressWarnings("unchecked")