mirror of https://github.com/grpc/grpc-java.git
core: fix NPE in ConfigSelectingClientCall
Fix the following bug: ManagedChannelImpl.ConfigSelectingClientCall may return early in start() leaving delegate null, and fails request() method after start(). Currently the bug can only be triggered when using xDS.
This commit is contained in:
parent
d4fa0ecc07
commit
d25ebaf57d
|
|
@ -1179,6 +1179,7 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
|||
return delegate;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void start(Listener<RespT> observer, Metadata headers) {
|
||||
PickSubchannelArgs args = new PickSubchannelArgsImpl(method, headers, callOptions);
|
||||
|
|
@ -1186,6 +1187,7 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
|||
Status status = result.getStatus();
|
||||
if (!status.isOk()) {
|
||||
executeCloseObserverInContext(observer, status);
|
||||
delegate = (ClientCall<ReqT, RespT>) NOOP_CALL;
|
||||
return;
|
||||
}
|
||||
ClientInterceptor interceptor = result.getInterceptor();
|
||||
|
|
@ -1226,6 +1228,29 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
|||
}
|
||||
}
|
||||
|
||||
private static final ClientCall<Object, Object> NOOP_CALL = new ClientCall<Object, Object>() {
|
||||
@Override
|
||||
public void start(Listener<Object> responseListener, Metadata headers) {}
|
||||
|
||||
@Override
|
||||
public void request(int numMessages) {}
|
||||
|
||||
@Override
|
||||
public void cancel(String message, Throwable cause) {}
|
||||
|
||||
@Override
|
||||
public void halfClose() {}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Object message) {}
|
||||
|
||||
// Always returns {@code false}, since this is only used when the startup of the call fails.
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminate the channel if termination conditions are met.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@ public class ConfigSelectingClientCallTest {
|
|||
ArgumentCaptor<Status> statusCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(callListener).onClose(statusCaptor.capture(), any(Metadata.class));
|
||||
assertThat(statusCaptor.getValue().getCode()).isEqualTo(Status.Code.FAILED_PRECONDITION);
|
||||
|
||||
// The call should not delegate to null and fail methods with NPE.
|
||||
configSelectingClientCall.request(1);
|
||||
}
|
||||
|
||||
private final class TestChannel extends Channel {
|
||||
|
|
|
|||
Loading…
Reference in New Issue