Merge pull request #18629 from AspirinSJL/backport_pf_fix_1.20.x

Backport pick_first fix to v1.20.x
pull/18661/head
Juanli Shen 6 years ago committed by GitHub
commit 5f13d8584e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  2. 26
      test/cpp/end2end/client_lb_end2end_test.cc

@ -188,8 +188,14 @@ void PickFirst::ShutdownLocked() {
void PickFirst::ExitIdleLocked() { void PickFirst::ExitIdleLocked() {
if (idle_) { if (idle_) {
idle_ = false; idle_ = false;
if (subchannel_list_ != nullptr && if (subchannel_list_ == nullptr ||
subchannel_list_->num_subchannels() > 0) { subchannel_list_->num_subchannels() == 0) {
grpc_error* error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No addresses to connect to");
channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error),
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
} else {
subchannel_list_->subchannel(0) subchannel_list_->subchannel(0)
->CheckConnectivityStateAndStartWatchingLocked(); ->CheckConnectivityStateAndStartWatchingLocked();
} }
@ -253,13 +259,19 @@ void PickFirst::UpdateLocked(UpdateArgs args) {
grpc_channel_args_destroy(new_args); grpc_channel_args_destroy(new_args);
if (subchannel_list->num_subchannels() == 0) { if (subchannel_list->num_subchannels() == 0) {
// Empty update or no valid subchannels. Unsubscribe from all current // Empty update or no valid subchannels. Unsubscribe from all current
// subchannels and put the channel in TRANSIENT_FAILURE. // subchannels.
subchannel_list_ = std::move(subchannel_list); // Empty list. subchannel_list_ = std::move(subchannel_list); // Empty list.
selected_ = nullptr; selected_ = nullptr;
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"); // If not idle, put the channel in TRANSIENT_FAILURE.
channel_control_helper()->UpdateState( // (If we are idle, then this will happen in ExitIdleLocked() if we
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), // haven't gotten a non-empty update by the time the application tries
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error))); // to start a new call.)
if (!idle_) {
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update");
channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error),
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
}
return; return;
} }
// If one of the subchannels in the new list is already in state // If one of the subchannels in the new list is already in state

@ -940,6 +940,32 @@ TEST_F(ClientLbEnd2endTest, PickFirstPendingUpdateAndSelectedSubchannelFails) {
WaitForServer(stub, 1, DEBUG_LOCATION, true /* ignore_failure */); WaitForServer(stub, 1, DEBUG_LOCATION, true /* ignore_failure */);
} }
TEST_F(ClientLbEnd2endTest, PickFirstStaysIdleUponEmptyUpdate) {
// Start server, send RPC, and make sure channel is READY.
const int kNumServers = 1;
StartServers(kNumServers);
auto channel = BuildChannel(""); // pick_first is the default.
auto stub = BuildStub(channel);
SetNextResolution(GetServersPorts());
CheckRpcSendOk(stub, DEBUG_LOCATION);
EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY);
// Stop server. Channel should go into state IDLE.
servers_[0]->Shutdown();
EXPECT_TRUE(WaitForChannelNotReady(channel.get()));
EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE);
// Now send resolver update that includes no addresses. Channel
// should stay in state IDLE.
SetNextResolution({});
EXPECT_FALSE(channel->WaitForStateChange(
GRPC_CHANNEL_IDLE, grpc_timeout_seconds_to_deadline(3)));
// Now bring the backend back up and send a non-empty resolver update,
// and then try to send an RPC. Channel should go back into state READY.
StartServer(0);
SetNextResolution(GetServersPorts());
CheckRpcSendOk(stub, DEBUG_LOCATION);
EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY);
}
TEST_F(ClientLbEnd2endTest, RoundRobin) { TEST_F(ClientLbEnd2endTest, RoundRobin) {
// Start servers and send one RPC per server. // Start servers and send one RPC per server.
const int kNumServers = 3; const int kNumServers = 3;

Loading…
Cancel
Save