diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java index f9e3ba7fd20..fb9e3bb9f01 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java @@ -1391,12 +1391,8 @@ private class LbHelperImpl extends LoadBalancer.Helper { @Override public AbstractSubchannel createSubchannel(CreateSubchannelArgs args) { syncContext.throwIfNotInThisSynchronizationContext(); - return createSubchannelInternal(args); - } - - private SubchannelImpl createSubchannelInternal(CreateSubchannelArgs args) { - // TODO(ejona): can we be even stricter? Like loadBalancer == null? - checkState(!terminated, "Channel is terminated"); + // No new subchannel should be created after load balancer has been shutdown. + checkState(!terminating, "Channel is being terminated"); return new SubchannelImpl(args, this); } @@ -1823,18 +1819,8 @@ private final class SubchannelImpl extends AbstractSubchannel { private void internalStart(final SubchannelStateListener listener) { checkState(!started, "already started"); checkState(!shutdown, "already shutdown"); + checkState(!terminating, "Channel is being terminated"); started = true; - // TODO(zhangkun): possibly remove the volatile of terminating when this whole method is - // required to be called from syncContext - if (terminating) { - syncContext.execute(new Runnable() { - @Override - public void run() { - listener.onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN)); - } - }); - return; - } final class ManagedInternalSubchannelCallback extends InternalSubchannel.Callback { // All callbacks are run in syncContext @Override