Merge pull request #18640 from lidizheng/v1.20.x
Bump version to v1.20.0-pre2
diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc
index e845d63..84a7f35 100644
--- a/src/core/ext/filters/client_channel/health/health_check_client.cc
+++ b/src/core/ext/filters/client_channel/health/health_check_client.cc
@@ -349,7 +349,6 @@
return;
}
// Initialize payload and batch.
- memset(&batch_, 0, sizeof(batch_));
payload_.context = context_;
batch_.payload = &payload_;
// on_complete callback takes ref, handled manually.
@@ -401,8 +400,6 @@
// Start batch.
StartBatch(&batch_);
// Initialize recv_trailing_metadata batch.
- memset(&recv_trailing_metadata_batch_, 0,
- sizeof(recv_trailing_metadata_batch_));
recv_trailing_metadata_batch_.payload = &payload_;
// Add recv_trailing_metadata op.
grpc_metadata_batch_init(&recv_trailing_metadata_);
@@ -507,7 +504,6 @@
// This re-uses the ref we're holding.
// Note: Can't just reuse batch_ here, since we don't know that all
// callbacks from the original batch have completed yet.
- memset(&recv_message_batch_, 0, sizeof(recv_message_batch_));
recv_message_batch_.payload = &payload_;
payload_.recv_message.recv_message = &recv_message_;
payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT(
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 86c6b25..3da0b59 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -188,8 +188,14 @@
void PickFirst::ExitIdleLocked() {
if (idle_) {
idle_ = false;
- if (subchannel_list_ != nullptr &&
- subchannel_list_->num_subchannels() > 0) {
+ if (subchannel_list_ == nullptr ||
+ 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)
->CheckConnectivityStateAndStartWatchingLocked();
}
@@ -253,13 +259,19 @@
grpc_channel_args_destroy(new_args);
if (subchannel_list->num_subchannels() == 0) {
// 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.
selected_ = nullptr;
- 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)));
+ // If not idle, put the channel in TRANSIENT_FAILURE.
+ // (If we are idle, then this will happen in ExitIdleLocked() if we
+ // haven't gotten a non-empty update by the time the application tries
+ // 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;
}
// If one of the subchannels in the new list is already in state
diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc
index cf21c4f..2fda160 100644
--- a/src/core/lib/iomgr/cfstream_handle.cc
+++ b/src/core/lib/iomgr/cfstream_handle.cc
@@ -192,4 +192,11 @@
}
}
+#else
+
+/* Creating a dummy function so that the grpc_cfstream library will be
+ * non-empty.
+ */
+void CFStreamDummy() {}
+
#endif
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index b6a79c1..adc76cb 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -172,7 +172,6 @@
detector.pollent = grpc_polling_entity_create_from_pollset(pollset);
detector.is_done = 0;
detector.success = 0;
- memset(&detector.response, 0, sizeof(detector.response));
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = (char*)GRPC_COMPUTE_ENGINE_DETECTION_HOST;
request.http.path = (char*)"/";
diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc
index 8be0b91..0930611 100644
--- a/src/core/lib/transport/transport.cc
+++ b/src/core/lib/transport/transport.cc
@@ -29,6 +29,7 @@
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/slice/slice_internal.h"
@@ -243,25 +244,26 @@
GRPC_ERROR_UNREF(error);
}
-typedef struct {
+struct made_transport_op {
grpc_closure outer_on_complete;
- grpc_closure* inner_on_complete;
+ grpc_closure* inner_on_complete = nullptr;
grpc_transport_op op;
-} made_transport_op;
+ made_transport_op() {
+ memset(&outer_on_complete, 0, sizeof(outer_on_complete));
+ }
+};
static void destroy_made_transport_op(void* arg, grpc_error* error) {
made_transport_op* op = static_cast<made_transport_op*>(arg);
GRPC_CLOSURE_SCHED(op->inner_on_complete, GRPC_ERROR_REF(error));
- gpr_free(op);
+ grpc_core::Delete<made_transport_op>(op);
}
grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete) {
- made_transport_op* op =
- static_cast<made_transport_op*>(gpr_malloc(sizeof(*op)));
+ made_transport_op* op = grpc_core::New<made_transport_op>();
GRPC_CLOSURE_INIT(&op->outer_on_complete, destroy_made_transport_op, op,
grpc_schedule_on_exec_ctx);
op->inner_on_complete = on_complete;
- memset(&op->op, 0, sizeof(op->op));
op->op.on_consumed = &op->outer_on_complete;
return &op->op;
}
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index 9d4b561..8631a1a 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -273,40 +273,40 @@
/** Transport op: a set of operations to perform on a transport as a whole */
typedef struct grpc_transport_op {
/** Called when processing of this op is done. */
- grpc_closure* on_consumed;
+ grpc_closure* on_consumed = nullptr;
/** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
- grpc_closure* on_connectivity_state_change;
- grpc_connectivity_state* connectivity_state;
+ grpc_closure* on_connectivity_state_change = nullptr;
+ grpc_connectivity_state* connectivity_state = nullptr;
/** should the transport be disconnected
* Error contract: the transport that gets this op must cause
* disconnect_with_error to be unref'ed after processing it */
- grpc_error* disconnect_with_error;
+ grpc_error* disconnect_with_error = nullptr;
/** what should the goaway contain?
* Error contract: the transport that gets this op must cause
* goaway_error to be unref'ed after processing it */
- grpc_error* goaway_error;
+ grpc_error* goaway_error = nullptr;
/** set the callback for accepting new streams;
this is a permanent callback, unlike the other one-shot closures.
If true, the callback is set to set_accept_stream_fn, with its
user_data argument set to set_accept_stream_user_data */
- bool set_accept_stream;
+ bool set_accept_stream = false;
void (*set_accept_stream_fn)(void* user_data, grpc_transport* transport,
- const void* server_data);
- void* set_accept_stream_user_data;
+ const void* server_data) = nullptr;
+ void* set_accept_stream_user_data = nullptr;
/** add this transport to a pollset */
- grpc_pollset* bind_pollset;
+ grpc_pollset* bind_pollset = nullptr;
/** add this transport to a pollset_set */
- grpc_pollset_set* bind_pollset_set;
+ grpc_pollset_set* bind_pollset_set = nullptr;
/** send a ping, if either on_initiate or on_ack is not NULL */
struct {
/** Ping may be delayed by the transport, on_initiate callback will be
called when the ping is actually being sent. */
- grpc_closure* on_initiate;
+ grpc_closure* on_initiate = nullptr;
/** Called when the ping ack is received */
- grpc_closure* on_ack;
+ grpc_closure* on_ack = nullptr;
} send_ping;
// If true, will reset the channel's connection backoff.
- bool reset_connect_backoff;
+ bool reset_connect_backoff = false;
/***************************************************************************
* remaining fields are initialized and used at the discretion of the
diff --git "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec" "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
index 984ca40..4bec215 100644
--- "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
+++ "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
@@ -101,7 +101,7 @@
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
- s.dependency '!ProtoCompiler', '3.6.1'
+ s.dependency '!ProtoCompiler', '3.7.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
diff --git "a/src/objective-c/\041ProtoCompiler.podspec" "b/src/objective-c/\041ProtoCompiler.podspec"
index 7892654..58d74be 100644
--- "a/src/objective-c/\041ProtoCompiler.podspec"
+++ "b/src/objective-c/\041ProtoCompiler.podspec"
@@ -36,7 +36,7 @@
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler'
- v = '3.6.1'
+ v = '3.7.0'
s.version = v
s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
s.description = <<-DESC
diff --git "a/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template" "b/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
index 5a416eb..741f9b7 100644
--- "a/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
+++ "b/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
@@ -103,7 +103,7 @@
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
- s.dependency '!ProtoCompiler', '3.6.1'
+ s.dependency '!ProtoCompiler', '3.7.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc
index 4244690..77f9db9 100644
--- a/test/cpp/end2end/client_lb_end2end_test.cc
+++ b/test/cpp/end2end/client_lb_end2end_test.cc
@@ -940,6 +940,32 @@
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) {
// Start servers and send one RPC per server.
const int kNumServers = 3;