aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2017-02-24 17:00:42 -0800
committerGravatar Craig Tiller <ctiller@google.com>2017-02-24 17:00:42 -0800
commitf30194f157c1027de4579b091a9e1be1621c4a55 (patch)
treeb5d4dcab5d34b04cae602c875806d50d19837aab
parent510f38a711a15aa0e4c87f4677dbdfe2da32cb81 (diff)
parentef33c8752f2020aa305e9965b594dc8a92a95629 (diff)
Merge branch 'bm_meta' of github.com:ctiller/grpc into bm_meta
-rw-r--r--.pylintrc3
-rw-r--r--WORKSPACE18
-rw-r--r--doc/service_config.md162
-rw-r--r--src/core/ext/client_channel/client_channel.c37
-rw-r--r--src/core/ext/client_channel/resolver.c25
-rw-r--r--src/core/ext/client_channel/resolver.h35
-rw-r--r--src/core/ext/client_channel/resolver_factory.h1
-rw-r--r--src/core/ext/client_channel/resolver_registry.c4
-rw-r--r--src/core/ext/client_channel/resolver_registry.h3
-rw-r--r--src/core/ext/resolver/dns/native/dns_resolver.c59
-rw-r--r--src/core/ext/resolver/sockaddr/sockaddr_resolver.c44
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c7
-rw-r--r--src/core/lib/channel/deadline_filter.c102
-rw-r--r--src/core/lib/channel/deadline_filter.h12
-rw-r--r--src/core/lib/iomgr/timer_generic.c18
-rw-r--r--src/core/lib/iomgr/timer_generic.h2
-rw-r--r--src/core/lib/iomgr/timer_uv.c12
-rw-r--r--src/core/lib/iomgr/timer_uv.h2
-rw-r--r--src/core/lib/surface/call.c145
-rw-r--r--src/core/lib/surface/server.c4
-rw-r--r--src/objective-c/tests/CronetUnitTests/CronetUnitTests.m82
-rw-r--r--src/python/grpcio/grpc/_channel.py7
-rw-r--r--src/python/grpcio/grpc/_common.py4
-rw-r--r--src/python/grpcio/grpc/_server.py21
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_connectivity_test.c39
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_test.c12
-rw-r--r--test/core/client_channel/resolvers/sockaddr_resolver_test.c17
-rw-r--r--test/core/end2end/fake_resolver.c2
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960bin0 -> 405 bytes
-rw-r--r--test/cpp/util/BUILD13
m---------third_party/gflags0
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_api.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_api.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_client.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_client.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_http_request.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_http_request.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_json.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_json.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_server.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_server.sh2
-rw-r--r--tools/internal_ci/linux/grpc_fuzzer_uri.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_fuzzer_uri.sh2
-rw-r--r--tools/internal_ci/linux/grpc_interop_badserver_java.cfg (renamed from tools/internal_ci/linux/grpc_interop.cfg)5
-rwxr-xr-xtools/internal_ci/linux/grpc_interop_badserver_java.sh (renamed from tools/internal_ci/linux/grpc_interop.sh)5
-rw-r--r--tools/internal_ci/linux/grpc_interop_badserver_python.cfg40
-rwxr-xr-xtools/internal_ci/linux/grpc_interop_badserver_python.sh41
-rw-r--r--tools/internal_ci/linux/grpc_interop_tocloud.cfg40
-rwxr-xr-xtools/internal_ci/linux/grpc_interop_tocloud.sh40
-rw-r--r--tools/internal_ci/linux/grpc_master.cfg5
-rwxr-xr-xtools/internal_ci/linux/grpc_master.sh2
-rw-r--r--tools/internal_ci/linux/grpc_portability_build_only.cfg39
-rw-r--r--tools/internal_ci/linux/grpc_portability_build_only.sh38
-rw-r--r--tools/internal_ci/windows/grpc_master.bat44
-rw-r--r--tools/internal_ci/windows/grpc_master.cfg39
-rwxr-xr-xtools/profiling/microbenchmarks/bm2bq.py1
-rw-r--r--tools/run_tests/generated/tests.json22
-rw-r--r--tools/run_tests/python_utils/start_port_server.py186
-rwxr-xr-xtools/run_tests/run_tests.py5
-rwxr-xr-xtools/run_tests/sanity/check_submodules.sh2
64 files changed, 986 insertions, 500 deletions
diff --git a/.pylintrc b/.pylintrc
index 1682488cb4..da2081b87e 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -30,6 +30,5 @@
#TODO: Enable too-many-nested-blocks
#TODO: Enable super-init-not-called
#TODO: Enable no-self-use
-#TODO: Enable no-member
-disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use,no-member
+disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use
diff --git a/WORKSPACE b/WORKSPACE
index 4f90f06d88..9b79d04cde 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -33,26 +33,36 @@ bind(
actual = "@submodule_gtest//:gtest",
)
+bind(
+ name = "gflags",
+ actual = "@com_github_gflags_gflags//:gflags",
+)
+
new_local_repository(
name = "submodule_boringssl",
- path = "third_party/boringssl-with-bazel",
build_file = "third_party/boringssl-with-bazel/BUILD",
+ path = "third_party/boringssl-with-bazel",
)
new_local_repository(
name = "submodule_zlib",
- path = "third_party/zlib",
build_file = "third_party/zlib.BUILD",
+ path = "third_party/zlib",
)
new_local_repository(
name = "submodule_protobuf",
- path = "third_party/protobuf",
build_file = "third_party/protobuf/BUILD",
+ path = "third_party/protobuf",
)
new_local_repository(
name = "submodule_gtest",
- path = "third_party/googletest",
build_file = "third_party/gtest.BUILD",
+ path = "third_party/googletest",
+)
+
+local_repository(
+ name = "com_github_gflags_gflags",
+ path = "third_party/gflags",
)
diff --git a/doc/service_config.md b/doc/service_config.md
index 2dabb83a37..ecc23817d1 100644
--- a/doc/service_config.md
+++ b/doc/service_config.md
@@ -12,105 +12,105 @@ The service config is a JSON string of the following form:
```
{
- # Load balancing policy name.
- # Supported values are 'round_robin' and 'grpclb'.
- # Optional; if unset, the default behavior is pick the first available
- # backend.
- # Note that if the resolver returns only balancer addresses and no
- # backend addresses, gRPC will always use the 'grpclb' policy,
- # regardless of what this field is set to.
+ // Load balancing policy name.
+ // Supported values are 'round_robin' and 'grpclb'.
+ // Optional; if unset, the default behavior is pick the first available
+ // backend.
+ // Note that if the resolver returns only balancer addresses and no
+ // backend addresses, gRPC will always use the 'grpclb' policy,
+ // regardless of what this field is set to.
'loadBalancingPolicy': string,
- # Per-method configuration. Optional.
+ // Per-method configuration. Optional.
'methodConfig': [
{
- # The names of the methods to which this method config applies. There
- # must be at least one name. Each name entry must be unique across the
- # entire service config. If the 'method' field is empty, then this
- # method config specifies the defaults for all methods for the specified
- # service.
- #
- # For example, let's say that the service config contains the following
- # method config entries:
- #
- # 'methodConfig': [
- # { 'name': [ { 'service': 'MyService' } ] ... },
- # { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... }
- # ]
- #
- # For a request for MyService/Foo, we will use the second entry, because
- # it exactly matches the service and method name.
- # For a request for MyService/Bar, we will use the first entry, because
- # it provides the default for all methods of MyService.
+ // The names of the methods to which this method config applies. There
+ // must be at least one name. Each name entry must be unique across the
+ // entire service config. If the 'method' field is empty, then this
+ // method config specifies the defaults for all methods for the specified
+ // service.
+ //
+ // For example, let's say that the service config contains the following
+ // method config entries:
+ //
+ // 'methodConfig': [
+ // { 'name': [ { 'service': 'MyService' } ] ... },
+ // { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... }
+ // ]
+ //
+ // For a request for MyService/Foo, we will use the second entry, because
+ // it exactly matches the service and method name.
+ // For a request for MyService/Bar, we will use the first entry, because
+ // it provides the default for all methods of MyService.
'name': [
{
- # RPC service name. Required.
- # If using gRPC with protobuf as the IDL, then this will be of
- # the form "pkg.service_name", where "pkg" is the package name
- # defined in the proto file.
+ // RPC service name. Required.
+ // If using gRPC with protobuf as the IDL, then this will be of
+ // the form "pkg.service_name", where "pkg" is the package name
+ // defined in the proto file.
'service': string,
- # RPC method name. Optional (see above).
+ // RPC method name. Optional (see above).
'method': string,
}
],
- # Whether RPCs sent to this method should wait until the connection is
- # ready by default. If false, the RPC will abort immediately if there
- # is a transient failure connecting to the server. Otherwise, gRPC will
- # attempt to connect until the deadline is exceeded.
- #
- # The value specified via the gRPC client API will override the value
- # set here. However, note that setting the value in the client API will
- # also affect transient errors encountered during name resolution,
- # which cannot be caught by the value here, since the service config
- # is obtained by the gRPC client via name resolution.
+ // Whether RPCs sent to this method should wait until the connection is
+ // ready by default. If false, the RPC will abort immediately if there
+ // is a transient failure connecting to the server. Otherwise, gRPC will
+ // attempt to connect until the deadline is exceeded.
+ //
+ // The value specified via the gRPC client API will override the value
+ // set here. However, note that setting the value in the client API will
+ // also affect transient errors encountered during name resolution,
+ // which cannot be caught by the value here, since the service config
+ // is obtained by the gRPC client via name resolution.
'waitForReady': bool,
- # The default timeout in seconds for RPCs sent to this method. This can
- # be overridden in code. If no reply is received in the specified amount
- # of time, the request is aborted and a deadline-exceeded error status
- # is returned to the caller.
- #
- # The actual deadline used will be the minimum of the value specified
- # here and the value set by the application via the gRPC client API.
- # If either one is not set, then the other will be used.
- # If neither is set, then the request has no deadline.
- #
- # The format of the value is that of the 'Duration' type defined here:
- # https://developers.google.com/protocol-buffers/docs/proto3#json
+ // The default timeout in seconds for RPCs sent to this method. This can
+ // be overridden in code. If no reply is received in the specified amount
+ // of time, the request is aborted and a deadline-exceeded error status
+ // is returned to the caller.
+ //
+ // The actual deadline used will be the minimum of the value specified
+ // here and the value set by the application via the gRPC client API.
+ // If either one is not set, then the other will be used.
+ // If neither is set, then the request has no deadline.
+ //
+ // The format of the value is that of the 'Duration' type defined here:
+ // https://developers.google.com/protocol-buffers/docs/proto3#json
'timeout': string,
- # The maximum allowed payload size for an individual request or object
- # in a stream (client->server) in bytes. The size which is measured is
- # the serialized, uncompressed payload in bytes. This applies both
- # to streaming and non-streaming requests.
- #
- # The actual value used is the minimum of the value specified here and
- # the value set by the application via the gRPC client API.
- # If either one is not set, then the other will be used.
- # If neither is set, then the built-in default is used.
- #
- # If a client attempts to send an object larger than this value, it
- # will not be sent and the client will see an error.
- # Note that 0 is a valid value, meaning that the request message must
- # be empty.
+ // The maximum allowed payload size for an individual request or object
+ // in a stream (client->server) in bytes. The size which is measured is
+ // the serialized, uncompressed payload in bytes. This applies both
+ // to streaming and non-streaming requests.
+ //
+ // The actual value used is the minimum of the value specified here and
+ // the value set by the application via the gRPC client API.
+ // If either one is not set, then the other will be used.
+ // If neither is set, then the built-in default is used.
+ //
+ // If a client attempts to send an object larger than this value, it
+ // will not be sent and the client will see an error.
+ // Note that 0 is a valid value, meaning that the request message must
+ // be empty.
'maxRequestMessageBytes': number,
- # The maximum allowed payload size for an individual response or object
- # in a stream (server->client) in bytes. The size which is measured is
- # the serialized, uncompressed payload in bytes. This applies both
- # to streaming and non-streaming requests.
- #
- # The actual value used is the minimum of the value specified here and
- # the value set by the application via the gRPC client API.
- # If either one is not set, then the other will be used.
- # If neither is set, then the built-in default is used.
- #
- # If a server attempts to send an object larger than this value, it
- # will not be sent, and the client will see an error.
- # Note that 0 is a valid value, meaning that the response message must
- # be empty.
+ // The maximum allowed payload size for an individual response or object
+ // in a stream (server->client) in bytes. The size which is measured is
+ // the serialized, uncompressed payload in bytes. This applies both
+ // to streaming and non-streaming requests.
+ //
+ // The actual value used is the minimum of the value specified here and
+ // the value set by the application via the gRPC client API.
+ // If either one is not set, then the other will be used.
+ // If neither is set, then the built-in default is used.
+ //
+ // If a server attempts to send an object larger than this value, it
+ // will not be sent, and the client will see an error.
+ // Note that 0 is a valid value, meaning that the response message must
+ // be empty.
'maxResponseMessageBytes': number
}
]
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index b1a4aa9a1c..6cbc333b83 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -230,7 +230,7 @@ static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
if (w->lb_policy == w->chand->lb_policy) {
if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
- grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
+ grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
w->chand->lb_policy = NULL;
}
@@ -386,11 +386,12 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
watch_lb_policy(exec_ctx, chand, lb_policy, state);
}
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
- &chand->on_resolver_result_changed);
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
+ &chand->resolver_result,
+ &chand->on_resolver_result_changed);
} else {
if (chand->resolver != NULL) {
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
+ grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
}
@@ -451,7 +452,7 @@ static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
+ grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
if (!chand->started_resolving) {
@@ -550,7 +551,7 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
chand->resolver = grpc_resolver_create(
exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
new_args != NULL ? new_args : args->channel_args,
- chand->interested_parties);
+ chand->interested_parties, chand->combiner);
if (proxy_name != NULL) gpr_free(proxy_name);
if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
if (chand->resolver == NULL) {
@@ -559,13 +560,23 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE;
}
+static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_resolver *resolver = arg;
+ grpc_resolver_shutdown_locked(exec_ctx, resolver);
+ GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
+}
+
/* Destructor for channel_data */
static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
if (chand->resolver != NULL) {
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
- GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_create(shutdown_resolver_locked, chand->resolver,
+ grpc_combiner_scheduler(chand->combiner, false)),
+ GRPC_ERROR_NONE);
}
if (chand->client_channel_factory != NULL) {
grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
@@ -846,8 +857,9 @@ static bool pick_subchannel_locked(
if (chand->resolver != NULL && !chand->started_resolving) {
chand->started_resolving = true;
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
- &chand->on_resolver_result_changed);
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
+ &chand->resolver_result,
+ &chand->on_resolver_result_changed);
}
if (chand->resolver != NULL) {
cpa = gpr_malloc(sizeof(*cpa));
@@ -1210,8 +1222,9 @@ static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
if (!chand->started_resolving && chand->resolver != NULL) {
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
chand->started_resolving = true;
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
- &chand->on_resolver_result_changed);
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
+ &chand->resolver_result,
+ &chand->on_resolver_result_changed);
}
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
diff --git a/src/core/ext/client_channel/resolver.c b/src/core/ext/client_channel/resolver.c
index 2ae4fe862e..b1a1faa6c9 100644
--- a/src/core/ext/client_channel/resolver.c
+++ b/src/core/ext/client_channel/resolver.c
@@ -32,10 +32,13 @@
*/
#include "src/core/ext/client_channel/resolver.h"
+#include "src/core/lib/iomgr/combiner.h"
void grpc_resolver_init(grpc_resolver *resolver,
- const grpc_resolver_vtable *vtable) {
+ const grpc_resolver_vtable *vtable,
+ grpc_combiner *combiner) {
resolver->vtable = vtable;
+ resolver->combiner = GRPC_COMBINER_REF(combiner, "resolver");
gpr_ref_init(&resolver->refs, 1);
}
@@ -62,20 +65,24 @@ void grpc_resolver_unref(grpc_resolver *resolver,
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
#endif
if (gpr_unref(&resolver->refs)) {
+ grpc_combiner *combiner = resolver->combiner;
resolver->vtable->destroy(exec_ctx, resolver);
+ GRPC_COMBINER_UNREF(exec_ctx, combiner, "resolver");
}
}
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
- resolver->vtable->shutdown(exec_ctx, resolver);
+void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
+ resolver->vtable->shutdown_locked(exec_ctx, resolver);
}
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
- resolver->vtable->channel_saw_error(exec_ctx, resolver);
+void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
+ resolver->vtable->channel_saw_error_locked(exec_ctx, resolver);
}
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **result, grpc_closure *on_complete) {
- resolver->vtable->next(exec_ctx, resolver, result, on_complete);
+void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **result,
+ grpc_closure *on_complete) {
+ resolver->vtable->next_locked(exec_ctx, resolver, result, on_complete);
}
diff --git a/src/core/ext/client_channel/resolver.h b/src/core/ext/client_channel/resolver.h
index 96ece92b9d..bbba424ca5 100644
--- a/src/core/ext/client_channel/resolver.h
+++ b/src/core/ext/client_channel/resolver.h
@@ -44,14 +44,16 @@ typedef struct grpc_resolver_vtable grpc_resolver_vtable;
struct grpc_resolver {
const grpc_resolver_vtable *vtable;
gpr_refcount refs;
+ grpc_combiner *combiner;
};
struct grpc_resolver_vtable {
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
- void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
- void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
- void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **result, grpc_closure *on_complete);
+ void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+ void (*channel_saw_error_locked)(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver);
+ void (*next_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **result, grpc_closure *on_complete);
};
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
@@ -70,21 +72,30 @@ void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
#endif
void grpc_resolver_init(grpc_resolver *resolver,
- const grpc_resolver_vtable *vtable);
+ const grpc_resolver_vtable *vtable,
+ grpc_combiner *combiner);
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver);
/** Notification that the channel has seen an error on some address.
- Can be used as a hint that re-resolution is desirable soon. */
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver);
+ Can be used as a hint that re-resolution is desirable soon.
+
+ Must be called from the combiner passed as a resolver_arg at construction
+ time.*/
+void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver);
/** Get the next result from the resolver. Expected to set \a *result with
new channel args and then schedule \a on_complete for execution.
If resolution is fatally broken, set \a *result to NULL and
- schedule \a on_complete. */
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **result, grpc_closure *on_complete);
+ schedule \a on_complete.
+
+ Must be called from the combiner passed as a resolver_arg at construction
+ time.*/
+void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **result,
+ grpc_closure *on_complete);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */
diff --git a/src/core/ext/client_channel/resolver_factory.h b/src/core/ext/client_channel/resolver_factory.h
index 3792ddca18..e3cd99ec5a 100644
--- a/src/core/ext/client_channel/resolver_factory.h
+++ b/src/core/ext/client_channel/resolver_factory.h
@@ -50,6 +50,7 @@ typedef struct grpc_resolver_args {
grpc_uri *uri;
const grpc_channel_args *args;
grpc_pollset_set *pollset_set;
+ grpc_combiner *combiner;
} grpc_resolver_args;
struct grpc_resolver_factory_vtable {
diff --git a/src/core/ext/client_channel/resolver_registry.c b/src/core/ext/client_channel/resolver_registry.c
index 5110a7cad9..f8e8bc9c39 100644
--- a/src/core/ext/client_channel/resolver_registry.c
+++ b/src/core/ext/client_channel/resolver_registry.c
@@ -133,7 +133,8 @@ static grpc_resolver_factory *resolve_factory(const char *target,
grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
const grpc_channel_args *args,
- grpc_pollset_set *pollset_set) {
+ grpc_pollset_set *pollset_set,
+ grpc_combiner *combiner) {
grpc_uri *uri = NULL;
char *canonical_target = NULL;
grpc_resolver_factory *factory =
@@ -144,6 +145,7 @@ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
resolver_args.uri = uri;
resolver_args.args = args;
resolver_args.pollset_set = pollset_set;
+ resolver_args.combiner = combiner;
resolver =
grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args);
grpc_uri_destroy(uri);
diff --git a/src/core/ext/client_channel/resolver_registry.h b/src/core/ext/client_channel/resolver_registry.h
index a4606463eb..e2c189cf0c 100644
--- a/src/core/ext/client_channel/resolver_registry.h
+++ b/src/core/ext/client_channel/resolver_registry.h
@@ -65,7 +65,8 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
should not be NULL. */
grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
const grpc_channel_args *args,
- grpc_pollset_set *pollset_set);
+ grpc_pollset_set *pollset_set,
+ grpc_combiner *combiner);
/** Find a resolver factory given a name and return an (owned-by-the-caller)
* reference to it */
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index c08b53ea04..96ac521a91 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -40,6 +40,7 @@
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h"
@@ -63,8 +64,6 @@ typedef struct {
/** pollset_set to drive the name resolution process */
grpc_pollset_set *interested_parties;
- /** mutex guarding the rest of the state */
- gpr_mu mu;
/** are we currently resolving? */
bool resolving;
/** which version of the result have we published? */
@@ -95,18 +94,20 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r);
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
- grpc_channel_args **target_result,
- grpc_closure *on_complete);
+static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *r);
+static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = {
- dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
+ dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked,
+ dns_next_locked};
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
+static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver;
- gpr_mu_lock(&r->mu);
if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer);
}
@@ -116,25 +117,21 @@ static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
GRPC_ERROR_CREATE("Resolver Shutdown"));
r->next_completion = NULL;
}
- gpr_mu_unlock(&r->mu);
}
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
+static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver;
- gpr_mu_lock(&r->mu);
if (!r->resolving) {
gpr_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(exec_ctx, r);
}
- gpr_mu_unlock(&r->mu);
}
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **target_result,
- grpc_closure *on_complete) {
+static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete) {
dns_resolver *r = (dns_resolver *)resolver;
- gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_result = target_result;
@@ -144,30 +141,26 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
} else {
dns_maybe_finish_next_locked(exec_ctx, r);
}
- gpr_mu_unlock(&r->mu);
}
-static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void dns_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
dns_resolver *r = arg;
- gpr_mu_lock(&r->mu);
r->have_retry_timer = false;
if (error == GRPC_ERROR_NONE) {
if (!r->resolving) {
dns_start_resolving_locked(exec_ctx, r);
}
}
- gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
}
-static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void dns_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
dns_resolver *r = arg;
grpc_channel_args *result = NULL;
- gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = false;
if (r->addresses != NULL) {
@@ -198,8 +191,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
} else {
gpr_log(GPR_DEBUG, "retrying immediately");
}
- grpc_closure_init(&r->on_retry, dns_on_retry_timer, r,
- grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&r->on_retry, dns_on_retry_timer_locked, r,
+ grpc_combiner_scheduler(r->base.combiner, false));
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry, now);
}
if (r->resolved_result != NULL) {
@@ -208,7 +201,6 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
r->resolved_result = result;
r->resolved_version++;
dns_maybe_finish_next_locked(exec_ctx, r);
- gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
}
@@ -221,7 +213,8 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
r->addresses = NULL;
grpc_resolve_address(
exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties,
- grpc_closure_create(dns_on_resolved, r, grpc_schedule_on_exec_ctx),
+ grpc_closure_create(dns_on_resolved_locked, r,
+ grpc_combiner_scheduler(r->base.combiner, false)),
&r->addresses);
}
@@ -240,7 +233,6 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
dns_resolver *r = (dns_resolver *)gr;
- gpr_mu_destroy(&r->mu);
if (r->resolved_result != NULL) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result);
}
@@ -264,8 +256,7 @@ static grpc_resolver *dns_create(grpc_exec_ctx *exec_ctx,
// Create resolver.
dns_resolver *r = gpr_malloc(sizeof(dns_resolver));
memset(r, 0, sizeof(*r));
- gpr_mu_init(&r->mu);
- grpc_resolver_init(&r->base, &dns_resolver_vtable);
+ grpc_resolver_init(&r->base, &dns_resolver_vtable, args->combiner);
r->name_to_resolve = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->channel_args = grpc_channel_args_copy(args->args);
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index a1365f6465..e7f66649b5 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -45,6 +45,7 @@
#include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/slice/slice_internal.h"
@@ -58,8 +59,6 @@ typedef struct {
grpc_lb_addresses *addresses;
/** channel args */
grpc_channel_args *channel_args;
- /** mutex guarding the rest of the state */
- gpr_mu mu;
/** have we published? */
bool published;
/** pending next completion, or NULL */
@@ -73,48 +72,43 @@ static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r);
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *r);
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
- grpc_channel_args **target_result,
- grpc_closure *on_complete);
+static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *r);
+static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = {
- sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
- sockaddr_next};
+ sockaddr_destroy, sockaddr_shutdown_locked,
+ sockaddr_channel_saw_error_locked, sockaddr_next_locked};
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
+static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
- gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_result = NULL;
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL;
}
- gpr_mu_unlock(&r->mu);
}
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
+static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
- gpr_mu_lock(&r->mu);
r->published = false;
sockaddr_maybe_finish_next_locked(exec_ctx, r);
- gpr_mu_unlock(&r->mu);
}
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **target_result,
- grpc_closure *on_complete) {
+static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
- gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_result = target_result;
sockaddr_maybe_finish_next_locked(exec_ctx, r);
- gpr_mu_unlock(&r->mu);
}
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@@ -131,7 +125,6 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
- gpr_mu_destroy(&r->mu);
grpc_lb_addresses_destroy(exec_ctx, r->addresses);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
gpr_free(r);
@@ -201,8 +194,7 @@ static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx,
memset(r, 0, sizeof(*r));
r->addresses = addresses;
r->channel_args = grpc_channel_args_copy(args->args);
- gpr_mu_init(&r->mu);
- grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
+ grpc_resolver_init(&r->base, &sockaddr_resolver_vtable, args->combiner);
return &r->base;
}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index d1fab25478..28a3166832 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -1114,8 +1114,11 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
grpc_chttp2_list_add_waiting_for_concurrency(t, s);
maybe_start_some_streams(exec_ctx, t);
} else {
- grpc_chttp2_cancel_stream(exec_ctx, t, s,
- GRPC_ERROR_CREATE("Transport closed"));
+ grpc_chttp2_cancel_stream(
+ exec_ctx, t, s,
+ grpc_error_set_int(GRPC_ERROR_CREATE("Transport closed"),
+ GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNAVAILABLE));
}
} else {
GPR_ASSERT(s->id != 0);
diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c
index 720cfb44e2..f9668be0fa 100644
--- a/src/core/lib/channel/deadline_filter.c
+++ b/src/core/lib/channel/deadline_filter.c
@@ -52,9 +52,6 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
grpc_call_element* elem = arg;
grpc_deadline_state* deadline_state = elem->call_data;
- gpr_mu_lock(&deadline_state->timer_mu);
- deadline_state->timer_pending = false;
- gpr_mu_unlock(&deadline_state->timer_mu);
if (error != GRPC_ERROR_CANCELLED) {
grpc_call_element_signal_error(
exec_ctx, elem,
@@ -66,53 +63,64 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
}
// Starts the deadline timer.
-static void start_timer_if_needed_locked(grpc_exec_ctx* exec_ctx,
- grpc_call_element* elem,
- gpr_timespec deadline) {
- grpc_deadline_state* deadline_state = elem->call_data;
- deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
- // Note: We do not start the timer if there is already a timer
- // pending. This should be okay, because this is only called from two
- // functions exported by this module: grpc_deadline_state_start(), which
- // starts the initial timer, and grpc_deadline_state_reset(), which
- // cancels any pre-existing timer before starting a new one. In
- // particular, we want to ensure that if grpc_deadline_state_start()
- // winds up trying to start the timer after grpc_deadline_state_reset()
- // has already done so, we ignore the value from the former.
- if (!deadline_state->timer_pending &&
- gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) {
- // Take a reference to the call stack, to be owned by the timer.
- GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
- deadline_state->timer_pending = true;
- grpc_closure_init(&deadline_state->timer_callback, timer_callback, elem,
- grpc_schedule_on_exec_ctx);
- grpc_timer_init(exec_ctx, &deadline_state->timer, deadline,
- &deadline_state->timer_callback,
- gpr_now(GPR_CLOCK_MONOTONIC));
- }
-}
static void start_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
gpr_timespec deadline) {
+ deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
+ if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) == 0) {
+ return;
+ }
grpc_deadline_state* deadline_state = elem->call_data;
- gpr_mu_lock(&deadline_state->timer_mu);
- start_timer_if_needed_locked(exec_ctx, elem, deadline);
- gpr_mu_unlock(&deadline_state->timer_mu);
+ grpc_deadline_timer_state cur_state;
+ grpc_closure* closure = NULL;
+retry:
+ cur_state =
+ (grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state);
+ switch (cur_state) {
+ case GRPC_DEADLINE_STATE_PENDING:
+ // Note: We do not start the timer if there is already a timer
+ return;
+ case GRPC_DEADLINE_STATE_FINISHED:
+ if (gpr_atm_rel_cas(&deadline_state->timer_state,
+ GRPC_DEADLINE_STATE_FINISHED,
+ GRPC_DEADLINE_STATE_PENDING)) {
+ // If we've already created and destroyed a timer, we always create a
+ // new closure: we have no other guarantee that the inlined closure is
+ // not in use (it may hold a pending call to timer_callback)
+ closure = grpc_closure_create(timer_callback, elem,
+ grpc_schedule_on_exec_ctx);
+ } else {
+ goto retry;
+ }
+ break;
+ case GRPC_DEADLINE_STATE_INITIAL:
+ if (gpr_atm_rel_cas(&deadline_state->timer_state,
+ GRPC_DEADLINE_STATE_INITIAL,
+ GRPC_DEADLINE_STATE_PENDING)) {
+ closure =
+ grpc_closure_init(&deadline_state->timer_callback, timer_callback,
+ elem, grpc_schedule_on_exec_ctx);
+ } else {
+ goto retry;
+ }
+ break;
+ }
+ GPR_ASSERT(closure);
+ GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
+ grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure,
+ gpr_now(GPR_CLOCK_MONOTONIC));
}
// Cancels the deadline timer.
-static void cancel_timer_if_needed_locked(grpc_exec_ctx* exec_ctx,
- grpc_deadline_state* deadline_state) {
- if (deadline_state->timer_pending) {
- grpc_timer_cancel(exec_ctx, &deadline_state->timer);
- deadline_state->timer_pending = false;
- }
-}
static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_deadline_state* deadline_state) {
- gpr_mu_lock(&deadline_state->timer_mu);
- cancel_timer_if_needed_locked(exec_ctx, deadline_state);
- gpr_mu_unlock(&deadline_state->timer_mu);
+ if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_PENDING,
+ GRPC_DEADLINE_STATE_FINISHED)) {
+ grpc_timer_cancel(exec_ctx, &deadline_state->timer);
+ } else {
+ // timer was either in STATE_INITAL (nothing to cancel)
+ // OR in STATE_FINISHED (again nothing to cancel)
+ }
}
// Callback run when the call is complete.
@@ -120,8 +128,8 @@ static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
grpc_deadline_state* deadline_state = arg;
cancel_timer_if_needed(exec_ctx, deadline_state);
// Invoke the next callback.
- deadline_state->next_on_complete->cb(
- exec_ctx, deadline_state->next_on_complete->cb_arg, error);
+ grpc_closure_run(exec_ctx, deadline_state->next_on_complete,
+ GRPC_ERROR_REF(error));
}
// Inject our own on_complete callback into op.
@@ -138,14 +146,12 @@ void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
grpc_deadline_state* deadline_state = elem->call_data;
memset(deadline_state, 0, sizeof(*deadline_state));
deadline_state->call_stack = call_stack;
- gpr_mu_init(&deadline_state->timer_mu);
}
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem) {
grpc_deadline_state* deadline_state = elem->call_data;
cancel_timer_if_needed(exec_ctx, deadline_state);
- gpr_mu_destroy(&deadline_state->timer_mu);
}
// Callback and associated state for starting the timer after call stack
@@ -187,10 +193,8 @@ void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
gpr_timespec new_deadline) {
grpc_deadline_state* deadline_state = elem->call_data;
- gpr_mu_lock(&deadline_state->timer_mu);
- cancel_timer_if_needed_locked(exec_ctx, deadline_state);
- start_timer_if_needed_locked(exec_ctx, elem, new_deadline);
- gpr_mu_unlock(&deadline_state->timer_mu);
+ cancel_timer_if_needed(exec_ctx, deadline_state);
+ start_timer_if_needed(exec_ctx, elem, new_deadline);
}
void grpc_deadline_state_client_start_transport_stream_op(
diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h
index bd2b84f79e..94717f6bc7 100644
--- a/src/core/lib/channel/deadline_filter.h
+++ b/src/core/lib/channel/deadline_filter.h
@@ -35,16 +35,18 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/timer.h"
+typedef enum grpc_deadline_timer_state {
+ GRPC_DEADLINE_STATE_INITIAL,
+ GRPC_DEADLINE_STATE_PENDING,
+ GRPC_DEADLINE_STATE_FINISHED
+} grpc_deadline_timer_state;
+
// State used for filters that enforce call deadlines.
// Must be the first field in the filter's call_data.
typedef struct grpc_deadline_state {
// We take a reference to the call stack for the timer callback.
grpc_call_stack* call_stack;
- // Guards access to timer_pending and timer.
- gpr_mu timer_mu;
- // True if the timer callback is currently pending.
- bool timer_pending;
- // The deadline timer.
+ gpr_atm timer_state;
grpc_timer timer;
grpc_closure timer_callback;
// Closure to invoke when the call is complete.
diff --git a/src/core/lib/iomgr/timer_generic.c b/src/core/lib/iomgr/timer_generic.c
index 8a5617e7c1..6d638bcbaa 100644
--- a/src/core/lib/iomgr/timer_generic.c
+++ b/src/core/lib/iomgr/timer_generic.c
@@ -180,25 +180,25 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
GPR_ASSERT(now.clock_type == g_clock_type);
timer->closure = closure;
timer->deadline = deadline;
- timer->triggered = 0;
if (!g_initialized) {
- timer->triggered = 1;
+ timer->pending = false;
grpc_closure_sched(
exec_ctx, timer->closure,
GRPC_ERROR_CREATE("Attempt to create timer before initialization"));
return;
}
+ gpr_mu_lock(&shard->mu);
+ timer->pending = true;
if (gpr_time_cmp(deadline, now) <= 0) {
- timer->triggered = 1;
+ timer->pending = false;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
+ gpr_mu_unlock(&shard->mu);
+ /* early out */
return;
}
- /* TODO(ctiller): check deadline expired */
-
- gpr_mu_lock(&shard->mu);
grpc_time_averaged_stats_add_sample(&shard->stats,
ts_to_dbl(gpr_time_sub(deadline, now)));
if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
@@ -243,9 +243,9 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
gpr_mu_lock(&shard->mu);
- if (!timer->triggered) {
+ if (timer->pending) {
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
- timer->triggered = 1;
+ timer->pending = false;
if (timer->heap_index == INVALID_HEAP_INDEX) {
list_remove(timer);
} else {
@@ -296,7 +296,7 @@ static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) {
}
timer = grpc_timer_heap_top(&shard->heap);
if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
- timer->triggered = 1;
+ timer->pending = false;
grpc_timer_heap_pop(&shard->heap);
return timer;
}
diff --git a/src/core/lib/iomgr/timer_generic.h b/src/core/lib/iomgr/timer_generic.h
index 9d901c7e68..1608dce9fb 100644
--- a/src/core/lib/iomgr/timer_generic.h
+++ b/src/core/lib/iomgr/timer_generic.h
@@ -40,7 +40,7 @@
struct grpc_timer {
gpr_timespec deadline;
uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
- int triggered;
+ bool pending;
struct grpc_timer *next;
struct grpc_timer *prev;
grpc_closure *closure;
diff --git a/src/core/lib/iomgr/timer_uv.c b/src/core/lib/iomgr/timer_uv.c
index fa2cdee964..f28a14405d 100644
--- a/src/core/lib/iomgr/timer_uv.c
+++ b/src/core/lib/iomgr/timer_uv.c
@@ -53,8 +53,8 @@ static void stop_uv_timer(uv_timer_t *handle) {
void run_expired_timer(uv_timer_t *handle) {
grpc_timer *timer = (grpc_timer *)handle->data;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- GPR_ASSERT(!timer->triggered);
- timer->triggered = 1;
+ GPR_ASSERT(timer->pending);
+ timer->pending = 0;
grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE);
stop_uv_timer(handle);
grpc_exec_ctx_finish(&exec_ctx);
@@ -67,11 +67,11 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
uv_timer_t *uv_timer;
timer->closure = closure;
if (gpr_time_cmp(deadline, now) <= 0) {
- timer->triggered = 1;
+ timer->pending = 0;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
return;
}
- timer->triggered = 0;
+ timer->pending = 1;
timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
uv_timer = gpr_malloc(sizeof(uv_timer_t));
uv_timer_init(uv_default_loop(), uv_timer);
@@ -81,8 +81,8 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
}
void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
- if (!timer->triggered) {
- timer->triggered = 1;
+ if (timer->pending) {
+ timer->pending = 0;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
stop_uv_timer((uv_timer_t *)timer->uv_timer);
}
diff --git a/src/core/lib/iomgr/timer_uv.h b/src/core/lib/iomgr/timer_uv.h
index 13cf8bd4fa..9870cd4a5c 100644
--- a/src/core/lib/iomgr/timer_uv.h
+++ b/src/core/lib/iomgr/timer_uv.h
@@ -41,7 +41,7 @@ struct grpc_timer {
/* This is actually a uv_timer_t*, but we want to keep platform-specific
types out of headers */
void *uv_timer;
- int triggered;
+ int pending;
};
#endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 48a1e586e1..3c563bcc6f 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -101,6 +101,17 @@ typedef struct {
grpc_error *error;
} received_status;
+static gpr_atm pack_received_status(received_status r) {
+ return r.is_set ? (1 | (gpr_atm)r.error) : 0;
+}
+
+static received_status unpack_received_status(gpr_atm atm) {
+ return (atm & 1) == 0
+ ? (received_status){.is_set = false, .error = GRPC_ERROR_NONE}
+ : (received_status){.is_set = true,
+ .error = (grpc_error *)(atm & ~(gpr_atm)1)};
+}
+
#define MAX_ERRORS_PER_BATCH 3
typedef struct batch_control {
@@ -142,8 +153,6 @@ struct grpc_call {
bool destroy_called;
/** flag indicating that cancellation is inherited */
bool cancellation_is_inherited;
- /** bitmask of live batches */
- uint8_t used_batches;
/** which ops are in-flight */
bool sent_initial_metadata;
bool sending_message;
@@ -165,8 +174,8 @@ struct grpc_call {
Element 0 is initial metadata, element 1 is trailing metadata. */
grpc_metadata_array *buffered_metadata[2];
- /* Received call statuses from various sources */
- received_status status[STATUS_SOURCE_COUNT];
+ /* Packed received call statuses from various sources */
+ gpr_atm status[STATUS_SOURCE_COUNT];
/* Call data useful used for reporting. Only valid after the call has
* completed */
@@ -446,7 +455,8 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- GRPC_ERROR_UNREF(c->status[i].error);
+ GRPC_ERROR_UNREF(
+ unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error);
}
grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
@@ -614,13 +624,12 @@ static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
*/
static bool get_final_status_from(
- grpc_call *call, status_source from_source, bool allow_ok_status,
+ grpc_call *call, grpc_error *error, bool allow_ok_status,
void (*set_value)(grpc_status_code code, void *user_data),
void *set_value_user_data, grpc_slice *details) {
grpc_status_code code;
const char *msg = NULL;
- grpc_error_get_status(call->status[from_source].error, call->send_deadline,
- &code, &msg, NULL);
+ grpc_error_get_status(error, call->send_deadline, &code, &msg, NULL);
if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false;
}
@@ -638,12 +647,15 @@ static void get_final_status(grpc_call *call,
void *user_data),
void *set_value_user_data, grpc_slice *details) {
int i;
+ received_status status[STATUS_SOURCE_COUNT];
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+ status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
+ }
if (grpc_call_error_trace) {
gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
- gpr_log(GPR_DEBUG, " %d: %s", i,
- grpc_error_string(call->status[i].error));
+ if (status[i].is_set) {
+ gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
}
}
}
@@ -653,9 +665,9 @@ static void get_final_status(grpc_call *call,
/* search for the best status we can present: ideally the error we use has a
clearly defined grpc-status, and we'll prefer that. */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set &&
- grpc_error_has_clear_grpc_status(call->status[i].error)) {
- if (get_final_status_from(call, (status_source)i, allow_ok_status != 0,
+ if (status[i].is_set &&
+ grpc_error_has_clear_grpc_status(status[i].error)) {
+ if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
set_value, set_value_user_data, details)) {
return;
}
@@ -663,8 +675,8 @@ static void get_final_status(grpc_call *call,
}
/* If no clearly defined status exists, search for 'anything' */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
- if (get_final_status_from(call, (status_source)i, allow_ok_status != 0,
+ if (status[i].is_set) {
+ if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
set_value, set_value_user_data, details)) {
return;
}
@@ -681,12 +693,13 @@ static void get_final_status(grpc_call *call,
static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
status_source source, grpc_error *error) {
- if (call->status[source].is_set) {
+ if (!gpr_atm_rel_cas(&call->status[source],
+ pack_received_status((received_status){
+ .is_set = false, .error = GRPC_ERROR_NONE}),
+ pack_received_status((received_status){
+ .is_set = true, .error = error}))) {
GRPC_ERROR_UNREF(error);
- return;
}
- call->status[source].is_set = true;
- call->status[source].error = error;
}
/*******************************************************************************
@@ -997,25 +1010,48 @@ static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
return !(flags & invalid_positions);
}
-static batch_control *allocate_batch_control(grpc_call *call) {
- size_t i;
- for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
- if ((call->used_batches & (1 << i)) == 0) {
- call->used_batches = (uint8_t)(call->used_batches | (uint8_t)(1 << i));
- return &call->active_batches[i];
- }
+static int batch_slot_for_op(grpc_op_type type) {
+ switch (type) {
+ case GRPC_OP_SEND_INITIAL_METADATA:
+ return 0;
+ case GRPC_OP_SEND_MESSAGE:
+ return 1;
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+ case GRPC_OP_SEND_STATUS_FROM_SERVER:
+ return 2;
+ case GRPC_OP_RECV_INITIAL_METADATA:
+ return 3;
+ case GRPC_OP_RECV_MESSAGE:
+ return 4;
+ case GRPC_OP_RECV_CLOSE_ON_SERVER:
+ case GRPC_OP_RECV_STATUS_ON_CLIENT:
+ return 5;
+ }
+ GPR_UNREACHABLE_CODE(return 123456789);
+}
+
+static batch_control *allocate_batch_control(grpc_call *call,
+ const grpc_op *ops,
+ size_t num_ops) {
+ int slot = batch_slot_for_op(ops[0].op);
+ for (size_t i = 1; i < num_ops; i++) {
+ int op_slot = batch_slot_for_op(ops[i].op);
+ slot = GPR_MIN(slot, op_slot);
+ }
+ batch_control *bctl = &call->active_batches[slot];
+ if (bctl->call != NULL) {
+ return NULL;
}
- return NULL;
+ memset(bctl, 0, sizeof(*bctl));
+ bctl->call = call;
+ return bctl;
}
static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_cq_completion *storage) {
batch_control *bctl = user_data;
grpc_call *call = bctl->call;
- gpr_mu_lock(&call->mu);
- call->used_batches = (uint8_t)(
- call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
- gpr_mu_unlock(&call->mu);
+ bctl->call = NULL;
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
}
@@ -1098,12 +1134,8 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
if (bctl->is_notify_tag_closure) {
/* unrefs bctl->error */
+ bctl->call = NULL;
grpc_closure_run(exec_ctx, bctl->notify_tag, error);
- gpr_mu_lock(&call->mu);
- bctl->call->used_batches =
- (uint8_t)(bctl->call->used_batches &
- ~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
- gpr_mu_unlock(&call->mu);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
} else {
/* unrefs bctl->error */
@@ -1315,6 +1347,11 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
finish_batch_step(exec_ctx, bctl);
}
+static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p,
+ grpc_cq_completion *completion) {
+ gpr_free(completion);
+}
+
static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_call *call, const grpc_op *ops,
size_t nops, void *notify_tag,
@@ -1329,32 +1366,34 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_metadata compression_md;
GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
-
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
- /* TODO(ctiller): this feels like it could be made lock-free */
- gpr_mu_lock(&call->mu);
- bctl = allocate_batch_control(call);
- memset(bctl, 0, sizeof(*bctl));
- bctl->call = call;
- bctl->notify_tag = notify_tag;
- bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
-
- grpc_transport_stream_op *stream_op = &bctl->op;
- memset(stream_op, 0, sizeof(*stream_op));
- stream_op->covered_by_poller = true;
-
if (nops == 0) {
- GRPC_CALL_INTERNAL_REF(call, "completion");
if (!is_notify_tag_closure) {
grpc_cq_begin_op(call->cq, notify_tag);
+ grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
+ free_no_op_completion, NULL,
+ gpr_malloc(sizeof(grpc_cq_completion)));
+ } else {
+ grpc_closure_sched(exec_ctx, notify_tag, GRPC_ERROR_NONE);
}
- gpr_mu_unlock(&call->mu);
- post_batch_completion(exec_ctx, bctl);
error = GRPC_CALL_OK;
goto done;
}
+ /* TODO(ctiller): this feels like it could be made lock-free */
+ bctl = allocate_batch_control(call, ops, nops);
+ if (bctl == NULL) {
+ return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+ }
+ bctl->notify_tag = notify_tag;
+ bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
+
+ gpr_mu_lock(&call->mu);
+ grpc_transport_stream_op *stream_op = &bctl->op;
+ memset(stream_op, 0, sizeof(*stream_op));
+ stream_op->covered_by_poller = true;
+
/* rewrite batch ops into a transport op */
for (i = 0; i < nops; i++) {
op = &ops[i];
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index e936e2015c..7210c69fb0 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -1198,7 +1198,9 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
crm->server_registered_method = rm;
crm->flags = rm->flags;
crm->has_host = has_host;
- crm->host = host;
+ if (has_host) {
+ crm->host = host;
+ }
crm->method = method;
}
GPR_ASSERT(slots <= UINT32_MAX);
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 5e3c59f8b3..e97f3d2d1a 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -321,44 +321,8 @@ unsigned int parse_h2_length(const char *field) {
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
- memset(ops, 0, sizeof(ops));
- op = ops;
- op->op = GRPC_OP_SEND_INITIAL_METADATA;
- op->data.send_initial_metadata.count = 2;
- op->data.send_initial_metadata.metadata = meta_c;
- op->flags = 0;
- op->reserved = NULL;
- op++;
- op->op = GRPC_OP_SEND_MESSAGE;
- op->data.send_message.send_message = request_payload;
- op->flags = 0;
- op->reserved = NULL;
- op++;
- op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
- op->flags = 0;
- op->reserved = NULL;
- op++;
- op->op = GRPC_OP_RECV_INITIAL_METADATA;
- op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
- op->flags = 0;
- op->reserved = NULL;
- op++;
- op->op = GRPC_OP_RECV_MESSAGE;
- op->data.recv_message.recv_message = &response_payload_recv;
- op->flags = 0;
- op->reserved = NULL;
- op++;
- op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
- op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
- op->data.recv_status_on_client.status = &status;
- op->data.recv_status_on_client.status_details = &details;
- op->flags = 0;
- op->reserved = NULL;
- op++;
- error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
- GPR_ASSERT(GRPC_CALL_OK == error);
-
- __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Coalescing"];
+ __weak XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Coalescing"];
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@@ -425,6 +389,46 @@ unsigned int parse_h2_length(const char *field) {
[expectation fulfill];
});
+ // Guarantees that server is listening to the port before client connects.
+ sleep(1);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 2;
+ op->data.send_initial_metadata.metadata = meta_c;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_MESSAGE;
+ op->data.send_message.send_message = request_payload;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->data.recv_message.recv_message = &response_payload_recv;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+ op->data.recv_status_on_client.status = &status;
+ op->data.recv_status_on_client.status_details = &details;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
cq_verify(cqv);
@@ -445,7 +449,7 @@ unsigned int parse_h2_length(const char *field) {
grpc_completion_queue_shutdown(cq);
drain_cq(cq);
grpc_completion_queue_destroy(cq);
-
+
[self waitForExpectationsWithTimeout:4 handler:nil];
}
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 26d93faf75..e602f39aeb 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -43,7 +43,6 @@ _USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__)
_EMPTY_FLAGS = 0
_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
-_EMPTY_METADATA = cygrpc.Metadata(())
_UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
@@ -138,8 +137,8 @@ def _abort(state, code, details):
state.code = code
state.details = details
if state.initial_metadata is None:
- state.initial_metadata = _EMPTY_METADATA
- state.trailing_metadata = _EMPTY_METADATA
+ state.initial_metadata = _common.EMPTY_METADATA
+ state.trailing_metadata = _common.EMPTY_METADATA
def _handle_event(event, state, response_deserializer):
@@ -435,7 +434,7 @@ def _start_unary_request(request, timeout, request_serializer):
deadline, deadline_timespec = _deadline(timeout)
serialized_request = _common.serialize(request, request_serializer)
if serialized_request is None:
- state = _RPCState((), _EMPTY_METADATA, _EMPTY_METADATA,
+ state = _RPCState((), _common.EMPTY_METADATA, _common.EMPTY_METADATA,
grpc.StatusCode.INTERNAL,
'Exception serializing request!')
rendezvous = _Rendezvous(state, None, None, deadline)
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index f9accd75a9..6879e1780b 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -37,7 +37,7 @@ import six
import grpc
from grpc._cython import cygrpc
-_EMPTY_METADATA = cygrpc.Metadata(())
+EMPTY_METADATA = cygrpc.Metadata(())
CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
cygrpc.ConnectivityState.idle:
@@ -107,7 +107,7 @@ def channel_args(options):
def cygrpc_metadata(application_metadata):
- return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
+ return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
cygrpc.Metadatum(encode(key), encode(value))
for key, value in application_metadata)
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index bf2743c16b..b8e7ea17f7 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -57,7 +57,6 @@ _CLOSED = 'closed'
_CANCELLED = 'cancelled'
_EMPTY_FLAGS = 0
-_EMPTY_METADATA = cygrpc.Metadata(())
_UNEXPECTED_EXIT_SERVER_GRACE = 1.0
@@ -143,7 +142,7 @@ def _abort(state, call, code, details):
effective_details = details if state.details is None else state.details
if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata(
- _EMPTY_METADATA, _EMPTY_FLAGS),
+ _common.EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_status_from_server(
_common.cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),)
@@ -416,7 +415,7 @@ def _send_response(rpc_event, state, serialized_response):
else:
if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata(
- _EMPTY_METADATA, _EMPTY_FLAGS),
+ _common.EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_response,
_EMPTY_FLAGS),)
state.initial_metadata_allowed = False
@@ -446,8 +445,8 @@ def _status(rpc_event, state, serialized_response):
]
if state.initial_metadata_allowed:
operations.append(
- cygrpc.operation_send_initial_metadata(_EMPTY_METADATA,
- _EMPTY_FLAGS))
+ cygrpc.operation_send_initial_metadata(
+ _common.EMPTY_METADATA, _EMPTY_FLAGS))
if serialized_response is not None:
operations.append(
cygrpc.operation_send_message(serialized_response,
@@ -549,12 +548,12 @@ def _find_method_handler(rpc_event, generic_handlers):
def _handle_unrecognized_method(rpc_event):
- operations = (
- cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS),
- cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
- cygrpc.operation_send_status_from_server(
- _EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
- b'Method not found!', _EMPTY_FLAGS),)
+ operations = (cygrpc.operation_send_initial_metadata(_common.EMPTY_METADATA,
+ _EMPTY_FLAGS),
+ cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
+ cygrpc.operation_send_status_from_server(
+ _common.EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
+ b'Method not found!', _EMPTY_FLAGS),)
rpc_state = _RPCState()
rpc_event.operation_call.start_server_batch(
operations, lambda ignored_event: (rpc_state, (),))
diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
index cfd37052de..3e3401165c 100644
--- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
@@ -36,14 +36,17 @@
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
+#include "src/core/ext/client_channel/resolver.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "test/core/util/test_config.h"
static gpr_mu g_mu;
static bool g_fail_resolution = true;
+static grpc_combiner *g_combiner;
static grpc_error *my_resolve_address(const char *name, const char *addr,
grpc_resolved_addresses **addrs) {
@@ -71,6 +74,7 @@ static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx,
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
args.uri = uri;
+ args.combiner = g_combiner;
grpc_resolver *resolver =
grpc_resolver_factory_create_resolver(exec_ctx, factory, &args);
grpc_resolver_factory_unref(factory);
@@ -96,11 +100,41 @@ static bool wait_loop(int deadline_seconds, gpr_event *ev) {
return false;
}
+typedef struct next_args {
+ grpc_resolver *resolver;
+ grpc_channel_args **result;
+ grpc_closure *on_complete;
+} next_args;
+
+static void call_resolver_next_now_lock_taken(grpc_exec_ctx *exec_ctx,
+ void *arg,
+ grpc_error *error_unused) {
+ next_args *a = arg;
+ grpc_resolver_next_locked(exec_ctx, a->resolver, a->result, a->on_complete);
+ gpr_free(a);
+}
+
+static void call_resolver_next_after_locking(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver,
+ grpc_channel_args **result,
+ grpc_closure *on_complete) {
+ next_args *a = gpr_malloc(sizeof(*a));
+ a->resolver = resolver;
+ a->result = result;
+ a->on_complete = on_complete;
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_create(call_resolver_next_now_lock_taken, a,
+ grpc_combiner_scheduler(resolver->combiner, false)),
+ GRPC_ERROR_NONE);
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
gpr_mu_init(&g_mu);
+ g_combiner = grpc_combiner_create(NULL);
grpc_blocking_resolve_address = my_resolve_address;
grpc_channel_args *result = (grpc_channel_args *)1;
@@ -108,7 +142,7 @@ int main(int argc, char **argv) {
grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test");
gpr_event ev1;
gpr_event_init(&ev1);
- grpc_resolver_next(
+ call_resolver_next_after_locking(
&exec_ctx, resolver, &result,
grpc_closure_create(on_done, &ev1, grpc_schedule_on_exec_ctx));
grpc_exec_ctx_flush(&exec_ctx);
@@ -117,7 +151,7 @@ int main(int argc, char **argv) {
gpr_event ev2;
gpr_event_init(&ev2);
- grpc_resolver_next(
+ call_resolver_next_after_locking(
&exec_ctx, resolver, &result,
grpc_closure_create(on_done, &ev2, grpc_schedule_on_exec_ctx));
grpc_exec_ctx_flush(&exec_ctx);
@@ -126,6 +160,7 @@ int main(int argc, char **argv) {
grpc_channel_args_destroy(&exec_ctx, result);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
+ GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
grpc_exec_ctx_finish(&exec_ctx);
grpc_shutdown();
diff --git a/test/core/client_channel/resolvers/dns_resolver_test.c b/test/core/client_channel/resolvers/dns_resolver_test.c
index 5603a57b5f..9dd5aed091 100644
--- a/test/core/client_channel/resolvers/dns_resolver_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_test.c
@@ -36,8 +36,11 @@
#include <grpc/support/log.h>
#include "src/core/ext/client_channel/resolver_registry.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "test/core/util/test_config.h"
+static grpc_combiner *g_combiner;
+
static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(string, 0);
@@ -48,6 +51,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri);
memset(&args, 0, sizeof(args));
args.uri = uri;
+ args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver != NULL);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
@@ -65,6 +69,7 @@ static void test_fails(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri);
memset(&args, 0, sizeof(args));
args.uri = uri;
+ args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver == NULL);
grpc_uri_destroy(uri);
@@ -76,6 +81,8 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
+ g_combiner = grpc_combiner_create(NULL);
+
dns = grpc_resolver_factory_lookup("dns");
test_succeeds(dns, "dns:10.2.1.1");
@@ -84,6 +91,11 @@ int main(int argc, char **argv) {
test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
grpc_resolver_factory_unref(dns);
+ {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
+ grpc_exec_ctx_finish(&exec_ctx);
+ }
grpc_shutdown();
return 0;
diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.c b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
index 10df78537c..68831ab7c7 100644
--- a/test/core/client_channel/resolvers/sockaddr_resolver_test.c
+++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
@@ -39,9 +39,12 @@
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "test/core/util/test_config.h"
+static grpc_combiner *g_combiner;
+
typedef struct on_resolution_arg {
char *expected_server_name;
grpc_channel_args *resolver_result;
@@ -62,6 +65,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri);
memset(&args, 0, sizeof(args));
args.uri = uri;
+ args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver != NULL);
@@ -71,8 +75,8 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_closure *on_resolution = grpc_closure_create(
on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx);
- grpc_resolver_next(&exec_ctx, resolver, &on_res_arg.resolver_result,
- on_resolution);
+ grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result,
+ on_resolution);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri);
@@ -88,6 +92,7 @@ static void test_fails(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri);
memset(&args, 0, sizeof(args));
args.uri = uri;
+ args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver == NULL);
grpc_uri_destroy(uri);
@@ -99,6 +104,8 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
+ g_combiner = grpc_combiner_create(NULL);
+
ipv4 = grpc_resolver_factory_lookup("ipv4");
ipv6 = grpc_resolver_factory_lookup("ipv6");
@@ -118,6 +125,12 @@ int main(int argc, char **argv) {
grpc_resolver_factory_unref(ipv4);
grpc_resolver_factory_unref(ipv6);
+
+ {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
+ grpc_exec_ctx_finish(&exec_ctx);
+ }
grpc_shutdown();
return 0;
diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c
index 4f05f69f01..8a37531449 100644
--- a/test/core/end2end/fake_resolver.c
+++ b/test/core/end2end/fake_resolver.c
@@ -213,7 +213,7 @@ static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx,
r->channel_args = grpc_channel_args_copy(args->args);
r->addresses = addresses;
gpr_mu_init(&r->mu);
- grpc_resolver_init(&r->base, &fake_resolver_vtable);
+ grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner);
return &r->base;
}
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960
new file mode 100644
index 0000000000..70ca3a336e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960
Binary files differ
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index 78eca8c3bd..f3cdc58986 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -37,14 +37,17 @@ cc_library(
hdrs = [
"test_config.h",
],
- deps = ["//:gpr"],
visibility = ["//test:__subpackages__"],
+ deps = [
+ "//:gpr",
+ "//external:gflags",
+ ],
)
cc_library(
name = "test_util",
srcs = [
-# "test/cpp/end2end/test_service_impl.cc",
+ # "test/cpp/end2end/test_service_impl.cc",
"byte_buffer_proto_helper.cc",
"create_test_channel.cc",
"string_ref_helper.cc",
@@ -58,6 +61,10 @@ cc_library(
"subprocess.h",
"test_credentials_provider.h",
],
- deps = ["//test/core/util:gpr_test_util", "//:grpc++", "//test/core/end2end:ssl_test_data"],
visibility = ["//test:__subpackages__"],
+ deps = [
+ "//:grpc++",
+ "//test/core/end2end:ssl_test_data",
+ "//test/core/util:gpr_test_util",
+ ],
)
diff --git a/third_party/gflags b/third_party/gflags
-Subproject f8a0efe03aa69b3336d8e228b37d4ccb17324b8
+Subproject 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26
diff --git a/tools/internal_ci/linux/grpc_fuzzer_api.cfg b/tools/internal_ci/linux/grpc_fuzzer_api.cfg
index a34fb9d47e..5c2592e933 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_api.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_api.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_api.sh b/tools/internal_ci/linux/grpc_fuzzer_api.sh
index c3cf1109de..b1f792e765 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_api.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_api.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.cfg b/tools/internal_ci/linux/grpc_fuzzer_client.cfg
index b1bce02282..1e8f688576 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_client.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_client.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.sh b/tools/internal_ci/linux/grpc_fuzzer_client.sh
index f9ff13d303..c03f92559c 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_client.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_client.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
index 215ce2bf9c..72482b62e3 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
index d9a73a622b..40179aa547 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg b/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
index 120e8f8f76..a4a0e8922e 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_http_request.sh b/tools/internal_ci/linux/grpc_fuzzer_http_request.sh
index d412d921ba..6dac4ed9ab 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_http_request.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_http_request.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_json.cfg b/tools/internal_ci/linux/grpc_fuzzer_json.cfg
index cab4f293ed..d22da2d705 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_json.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_json.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_json.sh b/tools/internal_ci/linux/grpc_fuzzer_json.sh
index d9869f6c30..b002ecb262 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_json.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_json.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
index c73aa819ee..cbf44ba29e 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
index 0a7187f8bf..51a8eb58bb 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_server.cfg b/tools/internal_ci/linux/grpc_fuzzer_server.cfg
index a1931cb891..7877d51792 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_server.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_server.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_server.sh b/tools/internal_ci/linux/grpc_fuzzer_server.sh
index e00e940382..b6648db34d 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_server.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_server.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_uri.cfg b/tools/internal_ci/linux/grpc_fuzzer_uri.cfg
index c312ae0464..134b3d06d6 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_uri.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_uri.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_uri.sh b/tools/internal_ci/linux/grpc_fuzzer_uri.sh
index 4137f8061c..e3e46515e2 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_uri.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_uri.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_interop.cfg b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
index 9259faf34d..e521b085c5 100644
--- a/tools/internal_ci/linux/grpc_interop.cfg
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
@@ -1,4 +1,3 @@
-#!/bin/bash
# Copyright 2017, Google Inc.
# All rights reserved.
#
@@ -31,11 +30,11 @@
# Config file for the internal CI (in protobuf text format)
# Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_interop.sh"
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_badserver_java.sh"
# grpc_interop tests can take 6+ hours to complete.
timeout_mins: 480
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/report.xml"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop.sh b/tools/internal_ci/linux/grpc_interop_badserver_java.sh
index 68bb4199e3..0985e657c6 100755
--- a/tools/internal_ci/linux/grpc_interop.sh
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.sh
@@ -37,6 +37,5 @@ cd $(dirname $0)/../../..
git submodule update --init
-tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --use_docker --http2_interop -t -j 12 $@ || FAILED="true"
-tools/run_tests/run_interop_tests.py -l java --use_docker --http2_badserver_interop $@ || FAILED="true"
-tools/run_tests/run_interop_tests.py -l python --use_docker --http2_badserver_interop $@ || FAILED="true"
+tools/run_tests/run_interop_tests.py -l java --use_docker --http2_badserver_interop $@
+
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
new file mode 100644
index 0000000000..940f760e97
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
@@ -0,0 +1,40 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_badserver_python.sh"
+# grpc_interop tests can take 6+ hours to complete.
+timeout_mins: 480
+action {
+ define_artifacts {
+ regex: "**/report.xml"
+ }
+}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.sh b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
new file mode 100755
index 0000000000..3fff537d2b
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+export LANG=en_US.UTF-8
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+tools/run_tests/run_interop_tests.py -l python --use_docker --http2_badserver_interop $@
+
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
new file mode 100644
index 0000000000..2b536446c1
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
@@ -0,0 +1,40 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_tocloud.sh"
+# grpc_interop tests can take 6+ hours to complete.
+timeout_mins: 480
+action {
+ define_artifacts {
+ regex: "**/report.xml"
+ }
+}
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.sh b/tools/internal_ci/linux/grpc_interop_tocloud.sh
new file mode 100755
index 0000000000..572001d944
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+export LANG=en_US.UTF-8
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+tools/run_tests/run_interop_tests.py -l all -s all --use_docker --http2_interop -t -j 12 $@
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/grpc_master.cfg
index 8ce2ef11a2..7536a91a67 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_master.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -32,7 +31,7 @@
# Location of the continuous shell script in repository.
build_file: "grpc/tools/internal_ci/linux/grpc_master.sh"
-timeout_mins: 60
+timeout_mins: 240
action {
define_artifacts {
regex: "**/sponge_log.xml"
diff --git a/tools/internal_ci/linux/grpc_master.sh b/tools/internal_ci/linux/grpc_master.sh
index ea77d11305..397e1bd713 100755
--- a/tools/internal_ci/linux/grpc_master.sh
+++ b/tools/internal_ci/linux/grpc_master.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_portability_build_only.cfg b/tools/internal_ci/linux/grpc_portability_build_only.cfg
new file mode 100644
index 0000000000..ce5be5abe9
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_portability_build_only.cfg
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_portability_build_only.sh"
+timeout_mins: 180
+action {
+ define_artifacts {
+ regex: "**report**.xml"
+ }
+}
diff --git a/tools/internal_ci/linux/grpc_portability_build_only.sh b/tools/internal_ci/linux/grpc_portability_build_only.sh
new file mode 100644
index 0000000000..9fac5bcac0
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_portability_build_only.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+tools/jenkins/run_jenkins_matrix.sh -f portability linux --build_only
diff --git a/tools/internal_ci/windows/grpc_master.bat b/tools/internal_ci/windows/grpc_master.bat
new file mode 100644
index 0000000000..4041c50313
--- /dev/null
+++ b/tools/internal_ci/windows/grpc_master.bat
@@ -0,0 +1,44 @@
+@rem Copyright 2017, Google Inc.
+@rem All rights reserved.
+@rem
+@rem Redistribution and use in source and binary forms, with or without
+@rem modification, are permitted provided that the following conditions are
+@rem met:
+@rem
+@rem * Redistributions of source code must retain the above copyright
+@rem notice, this list of conditions and the following disclaimer.
+@rem * Redistributions in binary form must reproduce the above
+@rem copyright notice, this list of conditions and the following disclaimer
+@rem in the documentation and/or other materials provided with the
+@rem distribution.
+@rem * Neither the name of Google Inc. nor the names of its
+@rem contributors may be used to endorse or promote products derived from
+@rem this software without specific prior written permission.
+@rem
+@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+setlocal
+
+@rem enter repo root
+cd /d %~dp0\..\..\..
+
+git submodule update --init
+
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x c_windows_dbg_sponge_log.xml --report_suite_name c_windows_dbg -l c -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x c_windows_opt_sponge_log.xml --report_suite_name c_windows_opt -l c -c opt
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x csharp_windows_dbg_sponge_log.xml --report_suite_name csharp_windows_dbg -l csharp -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x csharp_windows_opt_sponge_log.xml --report_suite_name csharp_windows_opt -l csharp -c opt
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x node_windows_dbg_sponge_log.xml --report_suite_name node_windows_dbg -l node -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x node_windows_opt_sponge_log.xml --report_suite_name node_windows_opt -l node -c opt
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x python_windows_dbg_sponge_log.xml --report_suite_name python_windows_dbg -l python -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x python_windows_opt_sponge_log.xml --report_suite_name python_windows_opt -l python -c opt
diff --git a/tools/internal_ci/windows/grpc_master.cfg b/tools/internal_ci/windows/grpc_master.cfg
new file mode 100644
index 0000000000..f90af11308
--- /dev/null
+++ b/tools/internal_ci/windows/grpc_master.cfg
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/windows/grpc_master.bat"
+timeout_mins: 360
+action {
+ define_artifacts {
+ regex: "**sponge_log.xml"
+ }
+}
diff --git a/tools/profiling/microbenchmarks/bm2bq.py b/tools/profiling/microbenchmarks/bm2bq.py
index d31921feef..3aa700388e 100755
--- a/tools/profiling/microbenchmarks/bm2bq.py
+++ b/tools/profiling/microbenchmarks/bm2bq.py
@@ -104,7 +104,6 @@ bm_specs = {
'tpl': [],
'dyn': ['request_size', 'bandwidth_kilobits'],
},
-<<<<<<< HEAD
'BM_ErrorStringOnNewError': {
'tpl': ['fixture'],
'dyn': [],
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 8b18e2fba2..65707a4623 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -79771,6 +79771,28 @@
},
{
"args": [
+ "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960"
+ ],
+ "ci_platforms": [
+ "linux"
+ ],
+ "cpu_cost": 0.1,
+ "exclude_configs": [
+ "tsan"
+ ],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "api_fuzzer_one_entry",
+ "platforms": [
+ "linux"
+ ],
+ "uses_polling": false
+ },
+ {
+ "args": [
"test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0597bbdd657fa4ed14443994c9147a1a7bbc205f"
],
"ci_platforms": [
diff --git a/tools/run_tests/python_utils/start_port_server.py b/tools/run_tests/python_utils/start_port_server.py
index 8ee7080168..4c9f6aac63 100644
--- a/tools/run_tests/python_utils/start_port_server.py
+++ b/tools/run_tests/python_utils/start_port_server.py
@@ -30,101 +30,109 @@
from __future__ import print_function
from six.moves import urllib
+import jobset
+import logging
import os
+import socket
import subprocess
-import tempfile
import sys
+import tempfile
import time
-import jobset
-import socket
+
def start_port_server(port_server_port):
- # check if a compatible port server is running
- # if incompatible (version mismatch) ==> start a new one
- # if not running ==> start a new one
- # otherwise, leave it up
- try:
- version = int(urllib.request.urlopen(
- 'http://localhost:%d/version_number' % port_server_port,
- timeout=10).read())
- print('detected port server running version %d' % version)
- running = True
- except Exception as e:
- print('failed to detect port server: %s' % sys.exc_info()[0])
- print(e.strerror)
- running = False
- if running:
- current_version = int(subprocess.check_output(
- [sys.executable, os.path.abspath('tools/run_tests/python_utils/port_server.py'),
- 'dump_version']))
- print('my port server is version %d' % current_version)
- running = (version >= current_version)
+ # check if a compatible port server is running
+ # if incompatible (version mismatch) ==> start a new one
+ # if not running ==> start a new one
+ # otherwise, leave it up
+ try:
+ version = int(
+ urllib.request.urlopen(
+ 'http://localhost:%d/version_number' % port_server_port,
+ timeout=10).read())
+ logging.info('detected port server running version %d', version)
+ running = True
+ except Exception as e:
+ logging.exception('failed to detect port server')
+ running = False
+ if running:
+ current_version = int(
+ subprocess.check_output([
+ sys.executable, os.path.abspath(
+ 'tools/run_tests/python_utils/port_server.py'),
+ 'dump_version'
+ ]))
+ logging.info('my port server is version %d', current_version)
+ running = (version >= current_version)
+ if not running:
+ logging.info('port_server version mismatch: killing the old one')
+ urllib.request.urlopen('http://localhost:%d/quitquitquit' %
+ port_server_port).read()
+ time.sleep(1)
if not running:
- print('port_server version mismatch: killing the old one')
- urllib.request.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
- time.sleep(1)
- if not running:
- fd, logfile = tempfile.mkstemp()
- os.close(fd)
- print('starting port_server, with log file %s' % logfile)
- args = [sys.executable, os.path.abspath('tools/run_tests/python_utils/port_server.py'),
- '-p', '%d' % port_server_port, '-l', logfile]
- env = dict(os.environ)
- env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
- if jobset.platform_string() == 'windows':
- # Working directory of port server needs to be outside of Jenkins
- # workspace to prevent file lock issues.
- tempdir = tempfile.mkdtemp()
- port_server = subprocess.Popen(
- args,
- env=env,
- cwd=tempdir,
- creationflags = 0x00000008, # detached process
- close_fds=True)
- else:
- port_server = subprocess.Popen(
- args,
- env=env,
- preexec_fn=os.setsid,
- close_fds=True)
- time.sleep(1)
- # ensure port server is up
- waits = 0
- while True:
- if waits > 10:
- print('killing port server due to excessive start up waits')
- port_server.kill()
- if port_server.poll() is not None:
- print('port_server failed to start')
- # try one final time: maybe another build managed to start one
+ fd, logfile = tempfile.mkstemp()
+ os.close(fd)
+ logging.info('starting port_server, with log file %s', logfile)
+ args = [
+ sys.executable,
+ os.path.abspath('tools/run_tests/python_utils/port_server.py'),
+ '-p', '%d' % port_server_port, '-l', logfile
+ ]
+ env = dict(os.environ)
+ env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
+ if jobset.platform_string() == 'windows':
+ # Working directory of port server needs to be outside of Jenkins
+ # workspace to prevent file lock issues.
+ tempdir = tempfile.mkdtemp()
+ port_server = subprocess.Popen(
+ args,
+ env=env,
+ cwd=tempdir,
+ creationflags=0x00000008, # detached process
+ close_fds=True)
+ else:
+ port_server = subprocess.Popen(
+ args, env=env, preexec_fn=os.setsid, close_fds=True)
time.sleep(1)
- try:
- urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
- timeout=1).read()
- print('last ditch attempt to contact port server succeeded')
- break
- except:
- traceback.print_exc()
- port_log = open(logfile, 'r').read()
- print(port_log)
- sys.exit(1)
- try:
- urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
+ # ensure port server is up
+ waits = 0
+ while True:
+ if waits > 10:
+ logging.warning(
+ 'killing port server due to excessive start up waits')
+ port_server.kill()
+ if port_server.poll() is not None:
+ logging.error('port_server failed to start')
+ # try one final time: maybe another build managed to start one
+ time.sleep(1)
+ try:
+ urllib.request.urlopen(
+ 'http://localhost:%d/get' % port_server_port,
timeout=1).read()
- print('port server is up and ready')
- break
- except socket.timeout:
- print('waiting for port_server: timeout')
- traceback.print_exc();
- time.sleep(1)
- waits += 1
- except urllib.error.URLError:
- print('waiting for port_server: urlerror')
- traceback.print_exc();
- time.sleep(1)
- waits += 1
- except:
- traceback.print_exc()
- port_server.kill()
- raise
-
+ logging.info(
+ 'last ditch attempt to contact port server succeeded')
+ break
+ except:
+ logging.exception(
+ 'final attempt to contact port server failed')
+ port_log = open(logfile, 'r').read()
+ print(port_log)
+ sys.exit(1)
+ try:
+ port_server_url = 'http://localhost:%d/get' % port_server_port
+ urllib.request.urlopen(port_server_url, timeout=1).read()
+ logging.info('port server is up and ready')
+ break
+ except socket.timeout:
+ logging.exception('while waiting for port_server')
+ time.sleep(1)
+ waits += 1
+ except urllib.error.URLError:
+ logging.exception('while waiting for port_server')
+ time.sleep(1)
+ waits += 1
+ except:
+ logging.exception('error while contacting port server at "%s".'
+ 'Will try killing it.', port_server_url)
+ port_server.kill()
+ raise
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index cfc2b04955..2d9eb29e7f 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -38,6 +38,7 @@ import collections
import glob
import itertools
import json
+import logging
import multiprocessing
import os
import os.path
@@ -84,8 +85,8 @@ def run_shell_command(cmd, env=None, cwd=None):
try:
subprocess.check_output(cmd, shell=True, env=env, cwd=cwd)
except subprocess.CalledProcessError as e:
- print("Error while running command '%s'. Exit status %d. Output:\n%s",
- e.cmd, e.returncode, e.output)
+ logging.exception("Error while running command '%s'. Exit status %d. Output:\n%s",
+ e.cmd, e.returncode, e.output)
raise
# SimpleConfig: just compile with CONFIG=config, and run the binary to test
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 0b68319d29..cfe4e2731c 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -44,7 +44,7 @@ cat << EOF | awk '{ print $1 }' | sort > $want_submodules
44c25c892a6229b20db7cd9dc05584ea865896de third_party/benchmark (v0.1.0-343-g44c25c8)
78684e5b222645828ca302e56b40b9daff2b2d27 third_party/boringssl (78684e5)
886e7d75368e3f4fab3f4d0d3584e4abfc557755 third_party/boringssl-with-bazel (version_for_cocoapods_7.0-857-g886e7d7)
- f8a0efe03aa69b3336d8e228b37d4ccb17324b88 third_party/gflags (v2.2.0)
+ 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0)
c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0)
a428e42072765993ff674fda72863c9f1aa2d268 third_party/protobuf (v3.1.0-alpha-1)
bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c third_party/thrift (bcad917)