From 1191b7202d86f01857f74d0709792fb74eac5a37 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 8 Feb 2017 11:56:52 -0800 Subject: [PATCH 01/14] Improve Node and libuv testing and test coverage Allow Node tests to run with or without UV, change default version to 7, add some portability tests. Also make some more core tests work with libuv --- CMakeLists.txt | 72 ++++ Makefile | 108 ++++++ binding.gyp | 26 +- build.yaml | 39 +- src/core/lib/iomgr/tcp_uv.c | 10 +- src/node/ext/completion_queue_threadpool.cc | 1 - templates/binding.gyp.template | 26 +- test/core/end2end/goaway_server_test.c | 6 + test/core/handshake/client_ssl.c | 11 + test/core/iomgr/resolve_address_test.c | 53 ++- test/core/iomgr/tcp_client_posix_test.c | 11 + test/core/iomgr/tcp_client_uv_test.c | 224 ++++++++++++ test/core/iomgr/tcp_server_uv_test.c | 341 ++++++++++++++++++ test/core/iomgr/timer_list_test.c | 11 + test/core/surface/completion_queue_test.c | 223 ------------ .../surface/completion_queue_threading_test.c | 290 +++++++++++++++ test/core/util/mock_endpoint.c | 6 + test/core/util/passthru_endpoint.c | 6 + test/core/util/test_config.c | 19 +- .../generated/sources_and_headers.json | 51 +++ tools/run_tests/generated/tests.json | 80 +++- tools/run_tests/helper_scripts/build_node.bat | 4 +- tools/run_tests/helper_scripts/build_node.sh | 9 +- .../run_tests/performance/run_worker_node.sh | 2 +- tools/run_tests/run_tests.py | 21 +- tools/run_tests/run_tests_matrix.py | 47 ++- vsprojects/buildtests_c.sln | 81 +++++ ...pc_completion_queue_threading_test.vcxproj | 199 ++++++++++ ...etion_queue_threading_test.vcxproj.filters | 21 ++ .../tcp_client_uv_test.vcxproj | 199 ++++++++++ .../tcp_client_uv_test.vcxproj.filters | 21 ++ .../tcp_server_uv_test.vcxproj | 199 ++++++++++ .../tcp_server_uv_test.vcxproj.filters | 21 ++ 33 files changed, 2140 insertions(+), 298 deletions(-) create mode 100644 test/core/iomgr/tcp_client_uv_test.c create mode 100644 test/core/iomgr/tcp_server_uv_test.c create mode 100644 test/core/surface/completion_queue_threading_test.c create mode 100644 vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj create mode 100644 vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj.filters create mode 100644 vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj create mode 100644 vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj.filters create mode 100644 vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj create mode 100644 vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj.filters diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f37b64c8e3..6951c33a2fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5990,6 +5990,30 @@ target_link_libraries(grpc_completion_queue_test gpr ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(grpc_completion_queue_threading_test + test/core/surface/completion_queue_threading_test.c +) + +target_include_directories(grpc_completion_queue_threading_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include +) + +target_link_libraries(grpc_completion_queue_threading_test + grpc_test_util + grpc + gpr_test_util + gpr +) + endif (gRPC_BUILD_TESTS) add_executable(grpc_create_jwt @@ -7280,6 +7304,30 @@ target_link_libraries(tcp_client_posix_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(tcp_client_uv_test + test/core/iomgr/tcp_client_uv_test.c +) + +target_include_directories(tcp_client_uv_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include +) + +target_link_libraries(tcp_client_uv_test + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(tcp_posix_test test/core/iomgr/tcp_posix_test.c ) @@ -7328,6 +7376,30 @@ target_link_libraries(tcp_server_posix_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(tcp_server_uv_test + test/core/iomgr/tcp_server_uv_test.c +) + +target_include_directories(tcp_server_uv_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include +) + +target_link_libraries(tcp_server_uv_test + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(time_averaged_stats_test test/core/iomgr/time_averaged_stats_test.c ) diff --git a/Makefile b/Makefile index d9d7f4090bd..578a5dd24f3 100644 --- a/Makefile +++ b/Makefile @@ -989,6 +989,7 @@ grpc_byte_buffer_reader_test: $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test grpc_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_channel_args_test grpc_channel_stack_test: $(BINDIR)/$(CONFIG)/grpc_channel_stack_test grpc_completion_queue_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_test +grpc_completion_queue_threading_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 @@ -1053,8 +1054,10 @@ sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test +tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test tcp_server_posix_test: $(BINDIR)/$(CONFIG)/tcp_server_posix_test +tcp_server_uv_test: $(BINDIR)/$(CONFIG)/tcp_server_uv_test time_averaged_stats_test: $(BINDIR)/$(CONFIG)/time_averaged_stats_test timeout_encoding_test: $(BINDIR)/$(CONFIG)/timeout_encoding_test timer_heap_test: $(BINDIR)/$(CONFIG)/timer_heap_test @@ -1344,6 +1347,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_channel_args_test \ $(BINDIR)/$(CONFIG)/grpc_channel_stack_test \ $(BINDIR)/$(CONFIG)/grpc_completion_queue_test \ + $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \ $(BINDIR)/$(CONFIG)/grpc_credentials_test \ $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \ $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test \ @@ -1394,8 +1398,10 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/sockaddr_utils_test \ $(BINDIR)/$(CONFIG)/socket_utils_test \ $(BINDIR)/$(CONFIG)/tcp_client_posix_test \ + $(BINDIR)/$(CONFIG)/tcp_client_uv_test \ $(BINDIR)/$(CONFIG)/tcp_posix_test \ $(BINDIR)/$(CONFIG)/tcp_server_posix_test \ + $(BINDIR)/$(CONFIG)/tcp_server_uv_test \ $(BINDIR)/$(CONFIG)/time_averaged_stats_test \ $(BINDIR)/$(CONFIG)/timeout_encoding_test \ $(BINDIR)/$(CONFIG)/timer_heap_test \ @@ -1734,6 +1740,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/grpc_channel_stack_test || ( echo test grpc_channel_stack_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_completion_queue_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_test || ( echo test grpc_completion_queue_test failed ; exit 1 ) + $(E) "[RUN] Testing grpc_completion_queue_threading_test" + $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_credentials_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_invalid_channel_args_test" @@ -1816,10 +1824,14 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_client_posix_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 ) + $(E) "[RUN] Testing tcp_client_uv_test" + $(Q) $(BINDIR)/$(CONFIG)/tcp_client_uv_test || ( echo test tcp_client_uv_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_posix_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_posix_test || ( echo test tcp_posix_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_server_posix_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_server_posix_test || ( echo test tcp_server_posix_test failed ; exit 1 ) + $(E) "[RUN] Testing tcp_server_uv_test" + $(Q) $(BINDIR)/$(CONFIG)/tcp_server_uv_test || ( echo test tcp_server_uv_test failed ; exit 1 ) $(E) "[RUN] Testing time_averaged_stats_test" $(Q) $(BINDIR)/$(CONFIG)/time_averaged_stats_test || ( echo test time_averaged_stats_test failed ; exit 1 ) $(E) "[RUN] Testing timeout_encoding_test" @@ -9632,6 +9644,38 @@ endif endif +GRPC_COMPLETION_QUEUE_THREADING_TEST_SRC = \ + test/core/surface/completion_queue_threading_test.c \ + +GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_COMPLETION_QUEUE_THREADING_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test: $(GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/surface/completion_queue_threading_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_completion_queue_threading_test: $(GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS:.o=.dep) +endif +endif + + GRPC_CREATE_JWT_SRC = \ test/core/security/create_jwt.c \ @@ -11680,6 +11724,38 @@ endif endif +TCP_CLIENT_UV_TEST_SRC = \ + test/core/iomgr/tcp_client_uv_test.c \ + +TCP_CLIENT_UV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_CLIENT_UV_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/tcp_client_uv_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/tcp_client_uv_test: $(TCP_CLIENT_UV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(TCP_CLIENT_UV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/tcp_client_uv_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_client_uv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_tcp_client_uv_test: $(TCP_CLIENT_UV_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TCP_CLIENT_UV_TEST_OBJS:.o=.dep) +endif +endif + + TCP_POSIX_TEST_SRC = \ test/core/iomgr/tcp_posix_test.c \ @@ -11744,6 +11820,38 @@ endif endif +TCP_SERVER_UV_TEST_SRC = \ + test/core/iomgr/tcp_server_uv_test.c \ + +TCP_SERVER_UV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_SERVER_UV_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/tcp_server_uv_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/tcp_server_uv_test: $(TCP_SERVER_UV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(TCP_SERVER_UV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/tcp_server_uv_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_server_uv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_tcp_server_uv_test: $(TCP_SERVER_UV_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TCP_SERVER_UV_TEST_OBJS:.o=.dep) +endif +endif + + TIME_AVERAGED_STATS_TEST_SRC = \ test/core/iomgr/time_averaged_stats_test.c \ diff --git a/binding.gyp b/binding.gyp index a46278a328b..c7ed04517d1 100644 --- a/binding.gyp +++ b/binding.gyp @@ -38,7 +38,12 @@ # https://n8.io/converting-a-c-library-to-gyp/ { 'variables': { - 'runtime%': 'node' + 'runtime%': 'node', + # UV integration in C core is disabled by default while bugs are ironed + # out. It can be re-enabled for one build by setting the npm config + # variable grpc_uv to true, and it can be re-enabled permanently by + # setting it to true here. + 'grpc_uv%': 'false' }, 'target_defaults': { 'include_dirs': [ @@ -49,11 +54,11 @@ 'GPR_BACKWARDS_COMPATIBILITY_MODE' ], 'conditions': [ - ['runtime=="node"', { + ['runtime=="node" and grpc_uv=="true"', { 'defines': [ # Disabling this while bugs are ironed out. Uncomment this to # re-enable libuv integration in C core. - # 'GRPC_UV' + 'GRPC_UV' ] }], ['OS!="win" and runtime=="electron"', { @@ -70,19 +75,10 @@ 'OPENSSL_NO_ASM' ] }, { - # Based on logic above, we know that this must be a non-Windows system - 'variables': { - # The output of "node --version" is "v[version]". We use cut to - # remove the first character. - 'target%': '0. - # io.js always reports versions >0 and always exports ALPN symbols. - # Therefore, Node's major version will be truthy if and only if it - # supports ALPN. The target is "[major].[minor].[patch]". We split by - # periods and take the first field to get the major version. + # As of the beginning of 2017, we only support versions of Node with + # embedded versions of OpenSSL that support ALPN 'defines': [ - 'TSI_OPENSSL_ALPN_SUPPORT=resource_user); gpr_free(tcp); @@ -119,6 +117,13 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } #endif +static void uv_close_callback(uv_handle_t *handle) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp *tcp = handle->data; + TCP_UNREF(&exec_ctx, tcp, "destroy"); + grpc_exec_ctx_finish(&exec_ctx); +} + static void alloc_uv_buf(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; @@ -311,7 +316,6 @@ static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { grpc_network_status_unregister_endpoint(ep); grpc_tcp *tcp = (grpc_tcp *)ep; uv_close((uv_handle_t *)tcp->handle, uv_close_callback); - TCP_UNREF(exec_ctx, tcp, "destroy"); } static char *uv_get_peer(grpc_endpoint *ep) { diff --git a/src/node/ext/completion_queue_threadpool.cc b/src/node/ext/completion_queue_threadpool.cc index 4881542f2d0..1917074dc2d 100644 --- a/src/node/ext/completion_queue_threadpool.cc +++ b/src/node/ext/completion_queue_threadpool.cc @@ -174,7 +174,6 @@ grpc_completion_queue *GetCompletionQueue() { } void CompletionQueueNext() { - gpr_log(GPR_DEBUG, "Called CompletionQueueNext"); CompletionQueueAsyncWorker::Next(); } diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template index 4b2f6ac12be..9d7034e18bc 100644 --- a/templates/binding.gyp.template +++ b/templates/binding.gyp.template @@ -40,7 +40,12 @@ # https://n8.io/converting-a-c-library-to-gyp/ { 'variables': { - 'runtime%': 'node' + 'runtime%': 'node', + # UV integration in C core is disabled by default while bugs are ironed + # out. It can be re-enabled for one build by setting the npm config + # variable grpc_uv to true, and it can be re-enabled permanently by + # setting it to true here. + 'grpc_uv%': 'false' }, 'target_defaults': { 'include_dirs': [ @@ -51,11 +56,11 @@ 'GPR_BACKWARDS_COMPATIBILITY_MODE' ], 'conditions': [ - ['runtime=="node"', { + ['runtime=="node" and grpc_uv=="true"', { 'defines': [ # Disabling this while bugs are ironed out. Uncomment this to # re-enable libuv integration in C core. - # 'GRPC_UV' + 'GRPC_UV' ] }], ['OS!="win" and runtime=="electron"', { @@ -72,19 +77,10 @@ 'OPENSSL_NO_ASM' ] }, { - # Based on logic above, we know that this must be a non-Windows system - 'variables': { - # The output of "node --version" is "v[version]". We use cut to - # remove the first character. - 'target%': '0. - # io.js always reports versions >0 and always exports ALPN symbols. - # Therefore, Node's major version will be truthy if and only if it - # supports ALPN. The target is "[major].[minor].[patch]". We split by - # periods and take the first field to get the major version. + # As of the beginning of 2017, we only support versions of Node with + # embedded versions of OpenSSL that support ALPN 'defines': [ - 'TSI_OPENSSL_ALPN_SUPPORT= #include #include diff --git a/test/core/handshake/client_ssl.c b/test/core/handshake/client_ssl.c index 613251b8355..1d853af5553 100644 --- a/test/core/handshake/client_ssl.c +++ b/test/core/handshake/client_ssl.c @@ -31,6 +31,11 @@ * */ +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + #include #include #include @@ -311,3 +316,9 @@ int main(int argc, char *argv[]) { GPR_ASSERT(!client_ssl_test("foo")); return 0; } + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c index 84f4ed4c90e..71e9fe5ba7e 100644 --- a/test/core/iomgr/resolve_address_test.c +++ b/test/core/iomgr/resolve_address_test.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" @@ -63,6 +62,7 @@ void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) { args->pollset_set = grpc_pollset_set_create(); grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset); args->addrs = NULL; + gpr_atm_rel_store(&args->done_atm, 0); } void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { @@ -85,8 +85,7 @@ static gpr_timespec n_sec_deadline(int seconds) { gpr_time_from_seconds(seconds, GPR_TIMESPAN)); } -static void actually_poll(void *argsp) { - args_struct *args = argsp; +static void poll_pollset_until_request_done(args_struct *args) { gpr_timespec deadline = n_sec_deadline(10); while (true) { bool done = gpr_atm_acq_load(&args->done_atm) != 0; @@ -111,12 +110,6 @@ static void actually_poll(void *argsp) { gpr_event_set(&args->ev, (void *)1); } -static void poll_pollset_until_request_done(args_struct *args) { - gpr_atm_rel_store(&args->done_atm, 0); - gpr_thd_id id; - gpr_thd_new(&id, actually_poll, args, NULL); -} - static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) { args_struct *args = argsp; @@ -124,23 +117,30 @@ static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp, GPR_ASSERT(args->addrs != NULL); GPR_ASSERT(args->addrs->naddrs > 0); gpr_atm_rel_store(&args->done_atm, 1); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL)); + gpr_mu_unlock(args->mu); } static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) { args_struct *args = argsp; GPR_ASSERT(err != GRPC_ERROR_NONE); gpr_atm_rel_store(&args->done_atm, 1); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL)); + gpr_mu_unlock(args->mu); } static void test_localhost(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); grpc_resolve_address( &exec_ctx, "localhost:1", NULL, args.pollset_set, grpc_closure_create(must_succeed, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } @@ -149,24 +149,40 @@ static void test_default_port(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); grpc_resolve_address( &exec_ctx, "localhost", "1", args.pollset_set, grpc_closure_create(must_succeed, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } -static void test_missing_default_port(void) { +static void test_non_numeric_default_port(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, "localhost", "https", args.pollset_set, + grpc_closure_create(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_missing_default_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); grpc_resolve_address( &exec_ctx, "localhost", NULL, args.pollset_set, grpc_closure_create(must_fail, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } @@ -175,11 +191,12 @@ static void test_ipv6_with_port(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); grpc_resolve_address( &exec_ctx, "[2001:db8::1]:1", NULL, args.pollset_set, grpc_closure_create(must_succeed, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } @@ -193,11 +210,12 @@ static void test_ipv6_without_port(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); grpc_resolve_address( &exec_ctx, kCases[i], "80", args.pollset_set, grpc_closure_create(must_succeed, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } @@ -212,11 +230,12 @@ static void test_invalid_ip_addresses(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); grpc_resolve_address( &exec_ctx, kCases[i], NULL, args.pollset_set, grpc_closure_create(must_fail, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } @@ -231,11 +250,12 @@ static void test_unparseable_hostports(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; args_struct args; args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); grpc_resolve_address( &exec_ctx, kCases[i], "1", args.pollset_set, grpc_closure_create(must_fail, &args, grpc_schedule_on_exec_ctx), &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); args_finish(&exec_ctx, &args); grpc_exec_ctx_finish(&exec_ctx); } @@ -247,6 +267,7 @@ int main(int argc, char **argv) { grpc_iomgr_init(); test_localhost(); test_default_port(); + test_non_numeric_default_port(); test_missing_default_port(); test_ipv6_with_port(); test_ipv6_without_port(); diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c index 0ea7a000eb4..e813cdbf2b6 100644 --- a/test/core/iomgr/tcp_client_posix_test.c +++ b/test/core/iomgr/tcp_client_posix_test.c @@ -31,6 +31,11 @@ * */ +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + #include "src/core/lib/iomgr/tcp_client.h" #include @@ -215,3 +220,9 @@ int main(int argc, char **argv) { gpr_free(g_pollset); return 0; } + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c new file mode 100644 index 00000000000..fc2360b4369 --- /dev/null +++ b/test/core/iomgr/tcp_client_uv_test.c @@ -0,0 +1,224 @@ +/* + * + * 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. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with libuv +#ifdef GRPC_UV + +#include + +#include + +#include "src/core/lib/iomgr/tcp_client.h" + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/iomgr/timer.h" +#include "test/core/util/test_config.h" + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; +static int g_connections_complete = 0; +static grpc_endpoint *g_connecting = NULL; + +static gpr_timespec test_deadline(void) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); +} + +static void finish_connection() { + gpr_mu_lock(g_mu); + g_connections_complete++; + GPR_ASSERT( + GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_ASSERT(g_connecting != NULL); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_endpoint_shutdown(exec_ctx, g_connecting); + grpc_endpoint_destroy(exec_ctx, g_connecting); + g_connecting = NULL; + finish_connection(); +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_ASSERT(g_connecting == NULL); + GPR_ASSERT(error != GRPC_ERROR_NONE); + finish_connection(); +} + +static void close_cb(uv_handle_t *handle) { + gpr_free(handle); +} + +static void connection_cb(uv_stream_t *server, int status) { + uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); + GPR_ASSERT(0 == status); + GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), client_handle)); + GPR_ASSERT(0 == uv_accept(server, (uv_stream_t *)client_handle)); + uv_close((uv_handle_t *)client_handle, close_cb); +} + +void test_succeeds(void) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + uv_tcp_t *svr_handle = gpr_malloc(sizeof(uv_tcp_t)); + int connections_complete_before; + grpc_closure done; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_DEBUG, "test_succeeds"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + /* create a dummy server */ + GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), svr_handle)); + GPR_ASSERT(0 == uv_tcp_bind(svr_handle, (struct sockaddr *)addr, 0)); + GPR_ASSERT(0 == uv_listen((uv_stream_t *)svr_handle, 1, connection_cb)); + + gpr_mu_lock(g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(g_mu); + + /* connect to it */ + GPR_ASSERT(uv_tcp_getsockname(svr_handle, (struct sockaddr *)addr, + (int *)&resolved_addr.len) == 0); + grpc_closure_init(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, + &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME)); + + gpr_mu_lock(g_mu); + + while (g_connections_complete == connections_complete_before) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), + GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5)))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + + // This will get cleaned up when the pollset runs again or gets shutdown + uv_close((uv_handle_t*)svr_handle, close_cb); + + gpr_mu_unlock(g_mu); + + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_fails(void) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + int connections_complete_before; + grpc_closure done; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_DEBUG, "test_fails"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + gpr_mu_lock(g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(g_mu); + + /* connect to a broken address */ + grpc_closure_init(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, + &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME)); + + gpr_mu_lock(g_mu); + + /* wait for the connection callback to finish */ + while (g_connections_complete == connections_complete_before) { + grpc_pollset_worker *worker = NULL; + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec polling_deadline = test_deadline(); + if (!grpc_timer_check(&exec_ctx, now, &polling_deadline)) { + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, now, + polling_deadline))); + } + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = gpr_malloc(grpc_pollset_size()); + grpc_pollset_init(g_pollset, &g_mu); + grpc_exec_ctx_finish(&exec_ctx); + test_succeeds(); + gpr_log(GPR_ERROR, "End of first test"); + test_fails(); + grpc_closure_init(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + return 0; +} + +#else /* GRPC_UV */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_UV */ diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c new file mode 100644 index 00000000000..07d09af127f --- /dev/null +++ b/test/core/iomgr/tcp_server_uv_test.c @@ -0,0 +1,341 @@ +/* + * + * 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. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with libuv +#ifdef GRPC_UV + +#include + +#include "src/core/lib/iomgr/tcp_server.h" + +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; +static int g_nconnects = 0; + +typedef struct on_connect_result { + /* Owns a ref to server. */ + grpc_tcp_server *server; + unsigned port_index; + unsigned fd_index; +} on_connect_result; + +typedef struct server_weak_ref { + grpc_tcp_server *server; + + /* arg is this server_weak_ref. */ + grpc_closure server_shutdown; +} server_weak_ref; + +static on_connect_result g_result = {NULL, 0, 0}; + +static void on_connect_result_init(on_connect_result *result) { + result->server = NULL; + result->port_index = 0; + result->fd_index = 0; +} + +static void on_connect_result_set(on_connect_result *result, + const grpc_tcp_server_acceptor *acceptor) { + result->server = grpc_tcp_server_ref(acceptor->from_server); + result->port_index = acceptor->port_index; + result->fd_index = acceptor->fd_index; +} + +static void server_weak_ref_shutdown(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + server_weak_ref *weak_ref = arg; + weak_ref->server = NULL; +} + +static void server_weak_ref_init(server_weak_ref *weak_ref) { + weak_ref->server = NULL; + grpc_closure_init(&weak_ref->server_shutdown, server_weak_ref_shutdown, + weak_ref, grpc_schedule_on_exec_ctx); +} + +/* Make weak_ref->server_shutdown a shutdown_starting cb on server. + grpc_tcp_server promises that the server object will live until + weak_ref->server_shutdown has returned. A strong ref on grpc_tcp_server + should be held until server_weak_ref_set() returns to avoid a race where the + server is deleted before the shutdown_starting cb is added. */ +static void server_weak_ref_set(server_weak_ref *weak_ref, + grpc_tcp_server *server) { + grpc_tcp_server_shutdown_starting_add(server, &weak_ref->server_shutdown); + weak_ref->server = server; +} + +static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, + grpc_pollset *pollset, + grpc_tcp_server_acceptor *acceptor) { + grpc_endpoint_shutdown(exec_ctx, tcp); + grpc_endpoint_destroy(exec_ctx, tcp); + + on_connect_result temp_result; + on_connect_result_set(&temp_result, acceptor); + gpr_free(acceptor); + + gpr_mu_lock(g_mu); + g_result = temp_result; + g_nconnects++; + GPR_ASSERT( + GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void test_no_op(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_start"); + grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_port"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + int port; + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == + GRPC_ERROR_NONE && + port > 0); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port_and_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_port_and_start"); + int port; + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == + GRPC_ERROR_NONE && + port > 0); + + grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void connect_cb(uv_connect_t *req, int status) { + GPR_ASSERT(status == 0); + gpr_free(req); +} + +static void close_cb(uv_handle_t *handle) { + gpr_free(handle); +} + +static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote, + socklen_t remote_len, on_connect_result *result) { + gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); + uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); + uv_connect_t *req = gpr_malloc(sizeof(uv_connect_t)); + int nconnects_before; + + gpr_mu_lock(g_mu); + nconnects_before = g_nconnects; + on_connect_result_init(&g_result); + GPR_ASSERT(uv_tcp_init(uv_default_loop(), client_handle) == 0); + gpr_log(GPR_DEBUG, "start connect"); + GPR_ASSERT(uv_tcp_connect(req, client_handle, remote, connect_cb) == 0); + gpr_log(GPR_DEBUG, "wait"); + while (g_nconnects == nconnects_before && + gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(exec_ctx, g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), deadline))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_log(GPR_DEBUG, "wait done"); + GPR_ASSERT(g_nconnects == nconnects_before + 1); + uv_close((uv_handle_t *)client_handle, close_cb); + *result = g_result; + + gpr_mu_unlock(g_mu); +} + +/* Tests a tcp server with multiple ports. */ +static void test_connect(unsigned n) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + grpc_resolved_address resolved_addr1; + struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; + struct sockaddr_storage *addr1 = + (struct sockaddr_storage *)resolved_addr1.addr; + int svr_port; + int svr1_port; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + unsigned i; + server_weak_ref weak_ref; + server_weak_ref_init(&weak_ref); + LOG_TEST("test_connect"); + gpr_log(GPR_INFO, "clients=%d", n); + memset(&resolved_addr, 0, sizeof(resolved_addr)); + memset(&resolved_addr1, 0, sizeof(resolved_addr1)); + resolved_addr.len = sizeof(struct sockaddr_storage); + resolved_addr1.len = sizeof(struct sockaddr_storage); + addr->ss_family = addr1->ss_family = AF_INET; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_add_port(s, &resolved_addr, &svr_port)); + GPR_ASSERT(svr_port > 0); + GPR_ASSERT(uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr) == 0); + /* Cannot use wildcard (port==0), because add_port() will try to reuse the + same port as a previous add_port(). */ + svr1_port = grpc_pick_unused_port_or_die(); + grpc_sockaddr_set_port(&resolved_addr1, svr1_port); + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &svr_port) == + GRPC_ERROR_NONE && + svr_port == svr1_port); + + grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); + + GPR_ASSERT(uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr1) == 0); + + for (i = 0; i < n; i++) { + on_connect_result result; + on_connect_result_init(&result); + tcp_connect(&exec_ctx, (struct sockaddr *)addr, + (socklen_t)resolved_addr.len, &result); + GPR_ASSERT(result.port_index == 0); + GPR_ASSERT(result.server == s); + if (weak_ref.server == NULL) { + server_weak_ref_set(&weak_ref, result.server); + } + grpc_tcp_server_unref(&exec_ctx, result.server); + + on_connect_result_init(&result); + tcp_connect(&exec_ctx, (struct sockaddr *)addr1, + (socklen_t)resolved_addr1.len, &result); + GPR_ASSERT(result.port_index == 1); + GPR_ASSERT(result.server == s); + grpc_tcp_server_unref(&exec_ctx, result.server); + } + + /* Weak ref to server valid until final unref. */ + GPR_ASSERT(weak_ref.server != NULL); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); + + /* Weak ref lost. */ + GPR_ASSERT(weak_ref.server == NULL); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = gpr_malloc(grpc_pollset_size()); + grpc_pollset_init(g_pollset, &g_mu); + + test_no_op(); + test_no_op_with_start(); + test_no_op_with_port(); + test_no_op_with_port_and_start(); + test_connect(1); + test_connect(10); + + grpc_closure_init(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + return 0; +} + +#else /* GRPC_UV */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_UV */ diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c index 8d7ac3fdaa1..85ad5277cc0 100644 --- a/test/core/iomgr/timer_list_test.c +++ b/test/core/iomgr/timer_list_test.c @@ -31,6 +31,11 @@ * */ +#include "src/core/lib/iomgr/port.h" + +// This test only works with the generic timer implementation +#ifdef GRPC_TIMER_USE_GENERIC + #include "src/core/lib/iomgr/timer.h" #include @@ -169,3 +174,9 @@ int main(int argc, char **argv) { destruction_test(); return 0; } + +#else /* GRPC_TIMER_USE_GENERIC */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_TIMER_USE_GENERIC */ diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index 1486d2508f6..07f6a9869b7 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include "src/core/lib/iomgr/iomgr.h" @@ -194,223 +193,6 @@ static void test_pluck_after_shutdown(void) { grpc_completion_queue_destroy(cc); } -struct thread_state { - grpc_completion_queue *cc; - void *tag; -}; - -static void pluck_one(void *arg) { - struct thread_state *state = arg; - grpc_completion_queue_pluck(state->cc, state->tag, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); -} - -static void test_too_many_plucks(void) { - grpc_event ev; - grpc_completion_queue *cc; - void *tags[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS]; - grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)]; - gpr_thd_id thread_ids[GPR_ARRAY_SIZE(tags)]; - struct thread_state thread_states[GPR_ARRAY_SIZE(tags)]; - gpr_thd_options thread_options = gpr_thd_options_default(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - unsigned i, j; - - LOG_TEST("test_too_many_plucks"); - - cc = grpc_completion_queue_create(NULL); - gpr_thd_options_set_joinable(&thread_options); - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - tags[i] = create_test_tag(); - for (j = 0; j < i; j++) { - GPR_ASSERT(tags[i] != tags[j]); - } - thread_states[i].cc = cc; - thread_states[i].tag = tags[i]; - gpr_thd_new(thread_ids + i, pluck_one, thread_states + i, &thread_options); - } - - /* wait until all other threads are plucking */ - gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1000)); - - ev = grpc_completion_queue_pluck(cc, create_test_tag(), - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - grpc_cq_begin_op(cc, tags[i]); - grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, - do_nothing_end_completion, NULL, &completions[i]); - } - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - gpr_thd_join(thread_ids[i]); - } - - shutdown_and_destroy(cc); - grpc_exec_ctx_finish(&exec_ctx); -} - -#define TEST_THREAD_EVENTS 10000 - -typedef struct test_thread_options { - gpr_event on_started; - gpr_event *phase1; - gpr_event on_phase1_done; - gpr_event *phase2; - gpr_event on_finished; - size_t events_triggered; - int id; - grpc_completion_queue *cc; -} test_thread_options; - -gpr_timespec ten_seconds_time(void) { - return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); -} - -static void free_completion(grpc_exec_ctx *exec_ctx, void *arg, - grpc_cq_completion *completion) { - gpr_free(completion); -} - -static void producer_thread(void *arg) { - test_thread_options *opt = arg; - int i; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, "producer %d started", opt->id); - gpr_event_set(&opt->on_started, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); - - gpr_log(GPR_INFO, "producer %d phase 1", opt->id); - for (i = 0; i < TEST_THREAD_EVENTS; i++) { - grpc_cq_begin_op(opt->cc, (void *)(intptr_t)1); - } - - gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id); - gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); - - gpr_log(GPR_INFO, "producer %d phase 2", opt->id); - for (i = 0; i < TEST_THREAD_EVENTS; i++) { - grpc_cq_end_op(&exec_ctx, opt->cc, (void *)(intptr_t)1, GRPC_ERROR_NONE, - free_completion, NULL, - gpr_malloc(sizeof(grpc_cq_completion))); - opt->events_triggered++; - grpc_exec_ctx_finish(&exec_ctx); - } - - gpr_log(GPR_INFO, "producer %d phase 2 done", opt->id); - gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void consumer_thread(void *arg) { - test_thread_options *opt = arg; - grpc_event ev; - - gpr_log(GPR_INFO, "consumer %d started", opt->id); - gpr_event_set(&opt->on_started, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); - - gpr_log(GPR_INFO, "consumer %d phase 1", opt->id); - - gpr_log(GPR_INFO, "consumer %d phase 1 done", opt->id); - gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); - - gpr_log(GPR_INFO, "consumer %d phase 2", opt->id); - for (;;) { - ev = grpc_completion_queue_next(opt->cc, ten_seconds_time(), NULL); - switch (ev.type) { - case GRPC_OP_COMPLETE: - GPR_ASSERT(ev.success); - opt->events_triggered++; - break; - case GRPC_QUEUE_SHUTDOWN: - gpr_log(GPR_INFO, "consumer %d phase 2 done", opt->id); - gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); - return; - case GRPC_QUEUE_TIMEOUT: - gpr_log(GPR_ERROR, "Invalid timeout received"); - abort(); - } - } -} - -static void test_threading(size_t producers, size_t consumers) { - test_thread_options *options = - gpr_malloc((producers + consumers) * sizeof(test_thread_options)); - gpr_event phase1 = GPR_EVENT_INIT; - gpr_event phase2 = GPR_EVENT_INIT; - grpc_completion_queue *cc = grpc_completion_queue_create(NULL); - size_t i; - size_t total_consumed = 0; - static int optid = 101; - - gpr_log(GPR_INFO, "%s: %" PRIuPTR " producers, %" PRIuPTR " consumers", - "test_threading", producers, consumers); - - /* start all threads: they will wait for phase1 */ - for (i = 0; i < producers + consumers; i++) { - gpr_thd_id id; - gpr_event_init(&options[i].on_started); - gpr_event_init(&options[i].on_phase1_done); - gpr_event_init(&options[i].on_finished); - options[i].phase1 = &phase1; - options[i].phase2 = &phase2; - options[i].events_triggered = 0; - options[i].cc = cc; - options[i].id = optid++; - GPR_ASSERT(gpr_thd_new(&id, - i < producers ? producer_thread : consumer_thread, - options + i, NULL)); - gpr_event_wait(&options[i].on_started, ten_seconds_time()); - } - - /* start phase1: producers will pre-declare all operations they will - complete */ - gpr_log(GPR_INFO, "start phase 1"); - gpr_event_set(&phase1, (void *)(intptr_t)1); - - gpr_log(GPR_INFO, "wait phase 1"); - for (i = 0; i < producers + consumers; i++) { - GPR_ASSERT(gpr_event_wait(&options[i].on_phase1_done, ten_seconds_time())); - } - gpr_log(GPR_INFO, "done phase 1"); - - /* start phase2: operations will complete, and consumers will consume them */ - gpr_log(GPR_INFO, "start phase 2"); - gpr_event_set(&phase2, (void *)(intptr_t)1); - - /* in parallel, we shutdown the completion channel - all events should still - be consumed */ - grpc_completion_queue_shutdown(cc); - - /* join all threads */ - gpr_log(GPR_INFO, "wait phase 2"); - for (i = 0; i < producers + consumers; i++) { - GPR_ASSERT(gpr_event_wait(&options[i].on_finished, ten_seconds_time())); - } - gpr_log(GPR_INFO, "done phase 2"); - - /* destroy the completion channel */ - grpc_completion_queue_destroy(cc); - - /* verify that everything was produced and consumed */ - for (i = 0; i < producers + consumers; i++) { - if (i < producers) { - GPR_ASSERT(options[i].events_triggered == TEST_THREAD_EVENTS); - } else { - total_consumed += options[i].events_triggered; - } - } - GPR_ASSERT(total_consumed == producers * TEST_THREAD_EVENTS); - - gpr_free(options); -} - int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); @@ -422,11 +204,6 @@ int main(int argc, char **argv) { test_cq_end_op(); test_pluck(); test_pluck_after_shutdown(); - test_too_many_plucks(); - test_threading(1, 1); - test_threading(1, 10); - test_threading(10, 1); - test_threading(10, 10); grpc_shutdown(); return 0; } diff --git a/test/core/surface/completion_queue_threading_test.c b/test/core/surface/completion_queue_threading_test.c new file mode 100644 index 00000000000..c41ee41e242 --- /dev/null +++ b/test/core/surface/completion_queue_threading_test.c @@ -0,0 +1,290 @@ +/* + * + * Copyright 2015, 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. + * + */ + +#include "src/core/lib/surface/completion_queue.h" + +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void *create_test_tag(void) { + static intptr_t i = 0; + return (void *)(++i); +} + +/* helper for tests to shutdown correctly and tersely */ +static void shutdown_and_destroy(grpc_completion_queue *cc) { + grpc_event ev; + grpc_completion_queue_shutdown(cc); + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + +static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg, + grpc_cq_completion *c) {} + +struct thread_state { + grpc_completion_queue *cc; + void *tag; +}; + +static void pluck_one(void *arg) { + struct thread_state *state = arg; + grpc_completion_queue_pluck(state->cc, state->tag, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +} + +static void test_too_many_plucks(void) { + grpc_event ev; + grpc_completion_queue *cc; + void *tags[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS]; + grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)]; + gpr_thd_id thread_ids[GPR_ARRAY_SIZE(tags)]; + struct thread_state thread_states[GPR_ARRAY_SIZE(tags)]; + gpr_thd_options thread_options = gpr_thd_options_default(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + unsigned i, j; + + LOG_TEST("test_too_many_plucks"); + + cc = grpc_completion_queue_create(NULL); + gpr_thd_options_set_joinable(&thread_options); + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + tags[i] = create_test_tag(); + for (j = 0; j < i; j++) { + GPR_ASSERT(tags[i] != tags[j]); + } + thread_states[i].cc = cc; + thread_states[i].tag = tags[i]; + gpr_thd_new(thread_ids + i, pluck_one, thread_states + i, &thread_options); + } + + /* wait until all other threads are plucking */ + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1000)); + + ev = grpc_completion_queue_pluck(cc, create_test_tag(), + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + grpc_cq_begin_op(cc, tags[i]); + grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, + do_nothing_end_completion, NULL, &completions[i]); + } + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + gpr_thd_join(thread_ids[i]); + } + + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); +} + +#define TEST_THREAD_EVENTS 10000 + +typedef struct test_thread_options { + gpr_event on_started; + gpr_event *phase1; + gpr_event on_phase1_done; + gpr_event *phase2; + gpr_event on_finished; + size_t events_triggered; + int id; + grpc_completion_queue *cc; +} test_thread_options; + +gpr_timespec ten_seconds_time(void) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); +} + +static void free_completion(grpc_exec_ctx *exec_ctx, void *arg, + grpc_cq_completion *completion) { + gpr_free(completion); +} + +static void producer_thread(void *arg) { + test_thread_options *opt = arg; + int i; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, "producer %d started", opt->id); + gpr_event_set(&opt->on_started, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); + + gpr_log(GPR_INFO, "producer %d phase 1", opt->id); + for (i = 0; i < TEST_THREAD_EVENTS; i++) { + grpc_cq_begin_op(opt->cc, (void *)(intptr_t)1); + } + + gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id); + gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); + + gpr_log(GPR_INFO, "producer %d phase 2", opt->id); + for (i = 0; i < TEST_THREAD_EVENTS; i++) { + grpc_cq_end_op(&exec_ctx, opt->cc, (void *)(intptr_t)1, GRPC_ERROR_NONE, + free_completion, NULL, + gpr_malloc(sizeof(grpc_cq_completion))); + opt->events_triggered++; + grpc_exec_ctx_finish(&exec_ctx); + } + + gpr_log(GPR_INFO, "producer %d phase 2 done", opt->id); + gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void consumer_thread(void *arg) { + test_thread_options *opt = arg; + grpc_event ev; + + gpr_log(GPR_INFO, "consumer %d started", opt->id); + gpr_event_set(&opt->on_started, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); + + gpr_log(GPR_INFO, "consumer %d phase 1", opt->id); + + gpr_log(GPR_INFO, "consumer %d phase 1 done", opt->id); + gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); + + gpr_log(GPR_INFO, "consumer %d phase 2", opt->id); + for (;;) { + ev = grpc_completion_queue_next(opt->cc, ten_seconds_time(), NULL); + switch (ev.type) { + case GRPC_OP_COMPLETE: + GPR_ASSERT(ev.success); + opt->events_triggered++; + break; + case GRPC_QUEUE_SHUTDOWN: + gpr_log(GPR_INFO, "consumer %d phase 2 done", opt->id); + gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); + return; + case GRPC_QUEUE_TIMEOUT: + gpr_log(GPR_ERROR, "Invalid timeout received"); + abort(); + } + } +} + +static void test_threading(size_t producers, size_t consumers) { + test_thread_options *options = + gpr_malloc((producers + consumers) * sizeof(test_thread_options)); + gpr_event phase1 = GPR_EVENT_INIT; + gpr_event phase2 = GPR_EVENT_INIT; + grpc_completion_queue *cc = grpc_completion_queue_create(NULL); + size_t i; + size_t total_consumed = 0; + static int optid = 101; + + gpr_log(GPR_INFO, "%s: %" PRIuPTR " producers, %" PRIuPTR " consumers", + "test_threading", producers, consumers); + + /* start all threads: they will wait for phase1 */ + for (i = 0; i < producers + consumers; i++) { + gpr_thd_id id; + gpr_event_init(&options[i].on_started); + gpr_event_init(&options[i].on_phase1_done); + gpr_event_init(&options[i].on_finished); + options[i].phase1 = &phase1; + options[i].phase2 = &phase2; + options[i].events_triggered = 0; + options[i].cc = cc; + options[i].id = optid++; + GPR_ASSERT(gpr_thd_new(&id, + i < producers ? producer_thread : consumer_thread, + options + i, NULL)); + gpr_event_wait(&options[i].on_started, ten_seconds_time()); + } + + /* start phase1: producers will pre-declare all operations they will + complete */ + gpr_log(GPR_INFO, "start phase 1"); + gpr_event_set(&phase1, (void *)(intptr_t)1); + + gpr_log(GPR_INFO, "wait phase 1"); + for (i = 0; i < producers + consumers; i++) { + GPR_ASSERT(gpr_event_wait(&options[i].on_phase1_done, ten_seconds_time())); + } + gpr_log(GPR_INFO, "done phase 1"); + + /* start phase2: operations will complete, and consumers will consume them */ + gpr_log(GPR_INFO, "start phase 2"); + gpr_event_set(&phase2, (void *)(intptr_t)1); + + /* in parallel, we shutdown the completion channel - all events should still + be consumed */ + grpc_completion_queue_shutdown(cc); + + /* join all threads */ + gpr_log(GPR_INFO, "wait phase 2"); + for (i = 0; i < producers + consumers; i++) { + GPR_ASSERT(gpr_event_wait(&options[i].on_finished, ten_seconds_time())); + } + gpr_log(GPR_INFO, "done phase 2"); + + /* destroy the completion channel */ + grpc_completion_queue_destroy(cc); + + /* verify that everything was produced and consumed */ + for (i = 0; i < producers + consumers; i++) { + if (i < producers) { + GPR_ASSERT(options[i].events_triggered == TEST_THREAD_EVENTS); + } else { + total_consumed += options[i].events_triggered; + } + } + GPR_ASSERT(total_consumed == producers * TEST_THREAD_EVENTS); + + gpr_free(options); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_too_many_plucks(); + test_threading(1, 1); + test_threading(1, 10); + test_threading(10, 1); + test_threading(10, 10); + grpc_shutdown(); + return 0; +} diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c index 04793bceabe..29ccbd270d8 100644 --- a/test/core/util/mock_endpoint.c +++ b/test/core/util/mock_endpoint.c @@ -31,6 +31,12 @@ * */ +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + #include "test/core/util/mock_endpoint.h" #include diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c index d42ec7f9e8c..4a1447554b6 100644 --- a/test/core/util/passthru_endpoint.c +++ b/test/core/util/passthru_endpoint.c @@ -31,6 +31,12 @@ * */ +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + #include "test/core/util/passthru_endpoint.h" #include diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c index d86ed94637c..986bbc95699 100644 --- a/test/core/util/test_config.c +++ b/test/core/util/test_config.c @@ -215,6 +215,19 @@ static void install_crash_handler() { #include #include +#define SIGNAL_NAMES_LENGTH 32 + +static const char * const signal_names[] = { + NULL, + "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", + "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", + "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", + "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", + "SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU", "SIGXFSZ", + "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", "SIGPWR", + "SIGSYS" +}; + static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)]; #define MAX_FRAMES 32 @@ -240,7 +253,11 @@ static void crash_handler(int signum, siginfo_t *info, void *data) { int addrlen; output_string("\n\n\n*******************************\nCaught signal "); - output_num(signum); + if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) { + output_string(signal_names[signum]); + } else { + output_num(signum); + } output_string("\n"); addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist)); diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 9bc82486d2b..5763532faac 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -938,6 +938,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "grpc_completion_queue_threading_test", + "src": [ + "test/core/surface/completion_queue_threading_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -2017,6 +2034,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "tcp_client_uv_test", + "src": [ + "test/core/iomgr/tcp_client_uv_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -2051,6 +2085,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "tcp_server_uv_test", + "src": [ + "test/core/iomgr/tcp_server_uv_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 2c7b0a6c822..a273e3f1202 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1101,6 +1101,28 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "grpc_completion_queue_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ @@ -1117,7 +1139,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "grpc_completion_queue_test", + "name": "grpc_completion_queue_threading_test", "platforms": [ "linux", "mac", @@ -1240,7 +1262,9 @@ ], "cpu_cost": 1.0, "exclude_configs": [], - "exclude_iomgrs": [], + "exclude_iomgrs": [ + "uv" + ], "flaky": false, "gtest": false, "language": "c", @@ -1727,9 +1751,7 @@ ], "cpu_cost": 1.0, "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], + "exclude_iomgrs": [], "flaky": false, "gtest": false, "language": "c", @@ -2055,6 +2077,30 @@ "posix" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 0.5, + "exclude_configs": [], + "exclude_iomgrs": [ + "native" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "tcp_client_uv_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ @@ -2099,6 +2145,30 @@ "posix" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "native" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "tcp_server_uv_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/tools/run_tests/helper_scripts/build_node.bat b/tools/run_tests/helper_scripts/build_node.bat index 82e82083486..233dacd3fb0 100644 --- a/tools/run_tests/helper_scripts/build_node.bat +++ b/tools/run_tests/helper_scripts/build_node.bat @@ -38,5 +38,7 @@ for /f "delims=v" %%v in ('node --version') do ( rmdir "%USERPROFILE%\.node-gyp\%%v\include\node\openssl" /S /Q ) + + @rem rebuild, because it probably failed the first time -call npm install --build-from-source \ No newline at end of file +call npm install --build-from-source %1 %2 diff --git a/tools/run_tests/helper_scripts/build_node.sh b/tools/run_tests/helper_scripts/build_node.sh index 8a928bb762c..df3acdac2b4 100755 --- a/tools/run_tests/helper_scripts/build_node.sh +++ b/tools/run_tests/helper_scripts/build_node.sh @@ -40,4 +40,11 @@ CONFIG=${CONFIG:-opt} # change to grpc repo root cd $(dirname $0)/../../.. -npm install --unsafe-perm --build-from-source +case "$CONFIG" in + 'dbg') config_flag='--debug' ;; + *) config_flag='--release' ;; +esac + +uv_flag=$2 + +npm install --unsafe-perm --build-from-source $uv_flag $config_flag diff --git a/tools/run_tests/performance/run_worker_node.sh b/tools/run_tests/performance/run_worker_node.sh index 9a53a311f40..7e24b326a4c 100755 --- a/tools/run_tests/performance/run_worker_node.sh +++ b/tools/run_tests/performance/run_worker_node.sh @@ -29,7 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. source ~/.nvm/nvm.sh -nvm use 4 +nvm use 7 set -ex diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 5aae3432e16..d0ab5b2e7ca 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -376,9 +376,13 @@ class NodeLanguage(object): _check_compiler(self.args.compiler, ['default', 'node0.12', 'node4', 'node5', 'node6', 'node7', 'electron1.3']) + if args.iomgr_platform == "uv": + self.use_uv = True + else: + self.use_uv = False if self.args.compiler == 'default': self.runtime = 'node' - self.node_version = '4' + self.node_version = '7' else: if self.args.compiler.startswith('electron'): self.runtime = 'electron' @@ -407,7 +411,8 @@ class NodeLanguage(object): build_script = 'pre_build_node' if self.runtime == 'electron': build_script += '_electron' - return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script), self.node_version]] + return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script), + self.node_version]] def make_targets(self): return [] @@ -417,14 +422,22 @@ class NodeLanguage(object): def build_steps(self): if self.platform == 'windows': - return [['tools\\run_tests\\helper_scripts\\build_node.bat']] + if config == 'dbg': + config_flag = '--debug' + else: + config_flag = '--release' + return [['tools\\run_tests\\helper_scripts\\build_node.bat', + '--grpc_uv={}'.format('true' if self.use_uv else 'false'), + config_flag]] else: build_script = 'build_node' if self.runtime == 'electron': build_script += '_electron' # building for electron requires a patch version self.node_version += '.0' - return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script), self.node_version]] + return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script), + self.node_version, + '--grpc_uv={}'.format('true' if self.use_uv else 'false')]] def post_tests_steps(self): return [] diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index 8f70a6d2ea9..5a109bd1a1a 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -81,7 +81,7 @@ def _workspace_jobspec(name, runtests_args=[], workspace_name=None, inner_jobs=_ return test_job -def _generate_jobs(languages, configs, platforms, +def _generate_jobs(languages, configs, platforms, iomgr_platform = 'native', arch=None, compiler=None, labels=[], extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): @@ -89,7 +89,7 @@ def _generate_jobs(languages, configs, platforms, for language in languages: for platform in platforms: for config in configs: - name = '%s_%s_%s' % (language, platform, config) + name = '%s_%s_%s_%s' % (language, platform, config, iomgr_platform) runtests_args = ['-l', language, '-c', config] if arch or compiler: @@ -156,14 +156,6 @@ def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): extra_args=extra_args, inner_jobs=inner_jobs) - # libuv tests - test_jobs += _generate_jobs(languages=['c'], - configs=['dbg', 'opt'], - platforms=['linux'], - labels=['libuv'], - extra_args=extra_args + ['--iomgr_platform=uv'], - inner_jobs=inner_jobs) - return test_jobs @@ -232,6 +224,14 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS) extra_args=extra_args, inner_jobs=inner_jobs) + test_jobs += _generate_jobs(languages=['c'], + configs=['dbg'], + platforms=['linux'], + iomgr_platform='uv', + labels=['portability'], + extra_args=extra_args, + inner_jobs=inner_jobs) + test_jobs += _generate_jobs(languages=['node'], configs=['dbg'], platforms=['linux'], @@ -240,6 +240,33 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS) labels=['portability'], extra_args=extra_args, inner_jobs=inner_jobs) + + test_jobs += _generate_jobs(languages=['node'], + configs=['dbg'], + platforms=['linux'], + iomgr_platform='uv', + labels=['portability'], + extra_args=extra_args, + inner_jobs=inner_jobs) + + test_jobs += _generate_jobs(languages=['node'], + configs=['dbg'], + platforms=['linux'], + arch='default', + compiler='node4', + labels=['portability'], + extra_args=extra_args, + inner_jobs=inner_jobs) + + test_jobs += _generate_jobs(languages=['node'], + configs=['dbg'], + platforms=['linux'], + arch='default', + compiler='node6', + labels=['portability'], + extra_args=extra_args, + inner_jobs=inner_jobs) + return test_jobs diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index f484f29a4b2..f630200657f 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -569,6 +569,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_completion_queue_test" {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_completion_queue_threading_test", "vcxproj\test\grpc_completion_queue_threading_test\grpc_completion_queue_threading_test.vcxproj", "{E6C389BC-0B47-D692-9BCD-758604CFC45B}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_create_jwt", "vcxproj\.\grpc_create_jwt\grpc_create_jwt.vcxproj", "{77971F8D-F583-3E77-0E3C-6C1FB6B1749C}" ProjectSection(myProperties) = preProject lib = "False" @@ -1456,6 +1467,28 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockaddr_utils_test", "vcxp {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcp_client_uv_test", "vcxproj\test\tcp_client_uv_test\tcp_client_uv_test.vcxproj", "{9814D850-F3BB-8C7A-4C78-2751C1E272F4}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcp_server_uv_test", "vcxproj\test\tcp_server_uv_test\tcp_server_uv_test.vcxproj", "{676FA8B1-4800-6F02-1E1D-30517FD9C7F4}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_tcp_server", "vcxproj\.\test_tcp_server\test_tcp_server.vcxproj", "{E3110C46-A148-FF65-08FD-3324829BE7FE}" ProjectSection(myProperties) = preProject lib = "True" @@ -2503,6 +2536,22 @@ Global {16CDF507-EB91-D76C-F0A7-A914ABFD8C17}.Release-DLL|Win32.Build.0 = Release|Win32 {16CDF507-EB91-D76C-F0A7-A914ABFD8C17}.Release-DLL|x64.ActiveCfg = Release|x64 {16CDF507-EB91-D76C-F0A7-A914ABFD8C17}.Release-DLL|x64.Build.0 = Release|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug|Win32.ActiveCfg = Debug|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug|x64.ActiveCfg = Debug|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release|Win32.ActiveCfg = Release|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release|x64.ActiveCfg = Release|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug|Win32.Build.0 = Debug|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug|x64.Build.0 = Debug|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release|Win32.Build.0 = Release|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release|x64.Build.0 = Release|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Debug-DLL|x64.Build.0 = Debug|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release-DLL|Win32.Build.0 = Release|Win32 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release-DLL|x64.ActiveCfg = Release|x64 + {E6C389BC-0B47-D692-9BCD-758604CFC45B}.Release-DLL|x64.Build.0 = Release|x64 {77971F8D-F583-3E77-0E3C-6C1FB6B1749C}.Debug|Win32.ActiveCfg = Debug|Win32 {77971F8D-F583-3E77-0E3C-6C1FB6B1749C}.Debug|x64.ActiveCfg = Debug|x64 {77971F8D-F583-3E77-0E3C-6C1FB6B1749C}.Release|Win32.ActiveCfg = Release|Win32 @@ -3767,6 +3816,38 @@ Global {529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release-DLL|Win32.Build.0 = Release|Win32 {529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release-DLL|x64.ActiveCfg = Release|x64 {529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release-DLL|x64.Build.0 = Release|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug|x64.ActiveCfg = Debug|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release|Win32.ActiveCfg = Release|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release|x64.ActiveCfg = Release|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug|Win32.Build.0 = Debug|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug|x64.Build.0 = Debug|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release|Win32.Build.0 = Release|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release|x64.Build.0 = Release|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug-DLL|x64.Build.0 = Debug|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release-DLL|Win32.Build.0 = Release|Win32 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release-DLL|x64.ActiveCfg = Release|x64 + {9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release-DLL|x64.Build.0 = Release|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug|x64.ActiveCfg = Debug|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release|Win32.ActiveCfg = Release|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release|x64.ActiveCfg = Release|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug|Win32.Build.0 = Debug|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug|x64.Build.0 = Debug|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release|Win32.Build.0 = Release|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release|x64.Build.0 = Release|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Debug-DLL|x64.Build.0 = Debug|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release-DLL|Win32.Build.0 = Release|Win32 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release-DLL|x64.ActiveCfg = Release|x64 + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4}.Release-DLL|x64.Build.0 = Release|x64 {E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|Win32.ActiveCfg = Debug|Win32 {E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|x64.ActiveCfg = Debug|x64 {E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj b/vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj new file mode 100644 index 00000000000..79d5d3377be --- /dev/null +++ b/vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E6C389BC-0B47-D692-9BCD-758604CFC45B} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + grpc_completion_queue_threading_test + static + Debug + static + Debug + + + grpc_completion_queue_threading_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj.filters b/vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj.filters new file mode 100644 index 00000000000..fa18cf24cb4 --- /dev/null +++ b/vsprojects/vcxproj/test/grpc_completion_queue_threading_test/grpc_completion_queue_threading_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\surface + + + + + + {610a0893-b941-7804-c634-7e87da165bc8} + + + {f1d10be6-3cec-cfc8-a663-f88d860cf243} + + + {2f9aae89-db75-dc2a-9687-2930fba7c6f2} + + + + diff --git a/vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj b/vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj new file mode 100644 index 00000000000..69643ca9d08 --- /dev/null +++ b/vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {9814D850-F3BB-8C7A-4C78-2751C1E272F4} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + tcp_client_uv_test + static + Debug + static + Debug + + + tcp_client_uv_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj.filters b/vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj.filters new file mode 100644 index 00000000000..99697aba413 --- /dev/null +++ b/vsprojects/vcxproj/test/tcp_client_uv_test/tcp_client_uv_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\iomgr + + + + + + {15a54a22-a533-eefa-6597-338c283e2936} + + + {184af337-9d94-9c81-4bf0-37452c61fafc} + + + {0ce112f9-44c9-5291-c73c-bef3f84f0806} + + + + diff --git a/vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj b/vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj new file mode 100644 index 00000000000..e553d091b84 --- /dev/null +++ b/vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {676FA8B1-4800-6F02-1E1D-30517FD9C7F4} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + tcp_server_uv_test + static + Debug + static + Debug + + + tcp_server_uv_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj.filters b/vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj.filters new file mode 100644 index 00000000000..e334e21a395 --- /dev/null +++ b/vsprojects/vcxproj/test/tcp_server_uv_test/tcp_server_uv_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\iomgr + + + + + + {848adafa-e931-cd69-49b3-483f9e8dbf77} + + + {3f3b9db4-63ef-fe87-8ef8-7048b510b224} + + + {cab05942-2e34-7335-58d0-f40c4db9d3ca} + + + + From 0c73a1ad8e60ffbb8f889651764e219dec184543 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 17 Feb 2017 14:50:26 -0800 Subject: [PATCH 02/14] Clang format --- test/core/iomgr/tcp_client_uv_test.c | 6 ++---- test/core/iomgr/tcp_server_uv_test.c | 4 +--- test/core/util/test_config.c | 17 +++++++---------- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c index fc2360b4369..f8938d0abb7 100644 --- a/test/core/iomgr/tcp_client_uv_test.c +++ b/test/core/iomgr/tcp_client_uv_test.c @@ -85,9 +85,7 @@ static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { finish_connection(); } -static void close_cb(uv_handle_t *handle) { - gpr_free(handle); -} +static void close_cb(uv_handle_t *handle) { gpr_free(handle); } static void connection_cb(uv_stream_t *server, int status) { uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); @@ -142,7 +140,7 @@ void test_succeeds(void) { } // This will get cleaned up when the pollset runs again or gets shutdown - uv_close((uv_handle_t*)svr_handle, close_cb); + uv_close((uv_handle_t *)svr_handle, close_cb); gpr_mu_unlock(g_mu); diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c index 07d09af127f..7b458c90f3d 100644 --- a/test/core/iomgr/tcp_server_uv_test.c +++ b/test/core/iomgr/tcp_server_uv_test.c @@ -199,9 +199,7 @@ static void connect_cb(uv_connect_t *req, int status) { gpr_free(req); } -static void close_cb(uv_handle_t *handle) { - gpr_free(handle); -} +static void close_cb(uv_handle_t *handle) { gpr_free(handle); } static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote, socklen_t remote_len, on_connect_result *result) { diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c index 986bbc95699..be159403b9d 100644 --- a/test/core/util/test_config.c +++ b/test/core/util/test_config.c @@ -217,16 +217,13 @@ static void install_crash_handler() { #define SIGNAL_NAMES_LENGTH 32 -static const char * const signal_names[] = { - NULL, - "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", - "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", - "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", - "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", - "SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU", "SIGXFSZ", - "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", "SIGPWR", - "SIGSYS" -}; +static const char *const signal_names[] = { + NULL, "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", + "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", "SIGSEGV", + "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD", + "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", + "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", + "SIGPWR", "SIGSYS"}; static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)]; From 88113f7b61c494f0873f50de14fc9f224bf7437f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 21 Feb 2017 10:04:29 -0800 Subject: [PATCH 03/14] Minor fixes to tests --- tools/run_tests/helper_scripts/pre_build_node.sh | 2 +- tools/run_tests/run_tests.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/helper_scripts/pre_build_node.sh b/tools/run_tests/helper_scripts/pre_build_node.sh index e63be9da523..083cb2bc771 100755 --- a/tools/run_tests/helper_scripts/pre_build_node.sh +++ b/tools/run_tests/helper_scripts/pre_build_node.sh @@ -32,7 +32,7 @@ NODE_VERSION=$1 source ~/.nvm/nvm.sh -nvm use $NODE_VERSION +nvm install $NODE_VERSION set -ex export GRPC_CONFIG=${CONFIG:-opt} diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index d0ab5b2e7ca..0558360a987 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -422,7 +422,7 @@ class NodeLanguage(object): def build_steps(self): if self.platform == 'windows': - if config == 'dbg': + if self.config == 'dbg': config_flag = '--debug' else: config_flag = '--release' From 009c85983250e5ec0f3dc8ef43a25a1596fead1d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 21 Feb 2017 18:15:37 -0800 Subject: [PATCH 04/14] Generalize build_node.bat argument propagation --- tools/run_tests/helper_scripts/build_node.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run_tests/helper_scripts/build_node.bat b/tools/run_tests/helper_scripts/build_node.bat index 233dacd3fb0..7a67769516f 100644 --- a/tools/run_tests/helper_scripts/build_node.bat +++ b/tools/run_tests/helper_scripts/build_node.bat @@ -41,4 +41,4 @@ for /f "delims=v" %%v in ('node --version') do ( @rem rebuild, because it probably failed the first time -call npm install --build-from-source %1 %2 +call npm install --build-from-source %* From acd0ba0ca34de5f5b42658c06aa6cd22dc15bd62 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 22 Feb 2017 13:29:38 -0800 Subject: [PATCH 05/14] Fix segfault in Node server destructor --- binding.gyp | 2 + build.yaml | 2 + src/node/ext/server.cc | 69 ----------------- src/node/ext/server.h | 1 + src/node/ext/server_generic.cc | 73 ++++++++++++++++++ src/node/ext/server_uv.cc | 133 +++++++++++++++++++++++++++++++++ 6 files changed, 211 insertions(+), 69 deletions(-) create mode 100644 src/node/ext/server_generic.cc create mode 100644 src/node/ext/server_uv.cc diff --git a/binding.gyp b/binding.gyp index c7ed04517d1..2b2072fa568 100644 --- a/binding.gyp +++ b/binding.gyp @@ -879,6 +879,8 @@ "src/node/ext/node_grpc.cc", "src/node/ext/server.cc", "src/node/ext/server_credentials.cc", + "src/node/ext/server_generic.cc", + "src/node/ext/server_uv.cc", "src/node/ext/timeval.cc", ], "dependencies": [ diff --git a/build.yaml b/build.yaml index c93dd429306..de1c6de4b9d 100644 --- a/build.yaml +++ b/build.yaml @@ -3946,6 +3946,8 @@ node_modules: - src/node/ext/node_grpc.cc - src/node/ext/server.cc - src/node/ext/server_credentials.cc + - src/node/ext/server_generic.cc + - src/node/ext/server_uv.cc - src/node/ext/timeval.cc openssl_fallback: base_uri: https://openssl.org/source/old/1.0.2/ diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 70d5b96f397..e83fdc49f25 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -77,8 +77,6 @@ using v8::Value; Nan::Callback *Server::constructor; Persistent Server::fun_tpl; -static Callback *shutdown_callback; - class NewCallOp : public Op { public: NewCallOp() { @@ -127,52 +125,6 @@ class NewCallOp : public Op { std::string GetTypeString() const { return "new_call"; } }; -class ServerShutdownOp : public Op { - public: - ServerShutdownOp(grpc_server *server): server(server) { - } - - ~ServerShutdownOp() { - } - - Local GetNodeValue() const { - return Nan::New(reinterpret_cast(server)); - } - - bool ParseOp(Local value, grpc_op *out, - shared_ptr resources) { - return true; - } - bool IsFinalOp() { - return false; - } - - grpc_server *server; - - protected: - std::string GetTypeString() const { return "shutdown"; } -}; - -NAN_METHOD(ServerShutdownCallback) { - if (!info[0]->IsNull()) { - return Nan::ThrowError("forceShutdown failed somehow"); - } - MaybeLocal maybe_result = Nan::To(info[1]); - Local result = maybe_result.ToLocalChecked(); - Local server_val = Nan::Get( - result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked(); - Local server_extern = server_val.As(); - grpc_server *server = reinterpret_cast(server_extern->Value()); - grpc_server_destroy(server); -} - -Server::Server(grpc_server *server) : wrapped_server(server) { -} - -Server::~Server() { - this->ShutdownServer(); -} - void Server::Init(Local exports) { HandleScope scope; Local tpl = Nan::New(New); @@ -187,11 +139,6 @@ void Server::Init(Local exports) { Local ctr = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(exports, Nan::New("Server").ToLocalChecked(), ctr); constructor = new Callback(ctr); - - Localcallback_tpl = - Nan::New(ServerShutdownCallback); - shutdown_callback = new Callback( - Nan::GetFunction(callback_tpl).ToLocalChecked()); } bool Server::HasInstance(Local val) { @@ -199,22 +146,6 @@ bool Server::HasInstance(Local val) { return Nan::New(fun_tpl)->HasInstance(val); } -void Server::ShutdownServer() { - if (this->wrapped_server != NULL) { - ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server); - unique_ptr ops(new OpVec()); - ops->push_back(unique_ptr(op)); - - grpc_server_shutdown_and_notify( - this->wrapped_server, GetCompletionQueue(), - new struct tag(new Callback(**shutdown_callback), ops.release(), - shared_ptr(nullptr), NULL)); - grpc_server_cancel_all_calls(this->wrapped_server); - CompletionQueueNext(); - this->wrapped_server = NULL; - } -} - NAN_METHOD(Server::New) { /* If this is not a constructor call, make a constructor call and return the result */ diff --git a/src/node/ext/server.h b/src/node/ext/server.h index 9e6a7bd1e0b..ab5fc210e8a 100644 --- a/src/node/ext/server.h +++ b/src/node/ext/server.h @@ -73,6 +73,7 @@ class Server : public Nan::ObjectWrap { static Nan::Persistent fun_tpl; grpc_server *wrapped_server; + grpc_completion_queue *shutdown_queue; }; } // namespace node diff --git a/src/node/ext/server_generic.cc b/src/node/ext/server_generic.cc new file mode 100644 index 00000000000..0cf20f754a8 --- /dev/null +++ b/src/node/ext/server_generic.cc @@ -0,0 +1,73 @@ +/* + * + * 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. + * + */ + +#ifndef GRPC_UV + +#include "server.h" + +#include +#include +#include "grpc/grpc.h" +#include "grpc/support/time.h" + +namespace grpc { +namespace node { + +Server::Server(grpc_server *server) : wrapped_server(server) { + shutdown_queue = grpc_completion_queue_create(NULL); + grpc_server_register_non_listening_completion_queue(server, shutdown_queue, + NULL); +} + +Server::~Server() { + this->ShutdownServer(); + grpc_completion_queue_shutdown(this->shutdown_queue); + grpc_completion_queue_destroy(this->shutdown_queue); +} + +void Server::ShutdownServer() { + if (this->wrapped_server != NULL) { + grpc_server_shutdown_and_notify(this->wrapped_server, this->shutdown_queue, + NULL); + grpc_server_cancel_all_calls(this->wrapped_server); + grpc_completion_queue_pluck(this->shutdown_queue, NULL, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_server_destroy(this->wrapped_server); + this->wrapped_server = NULL; + } +} + +} // namespace grpc +} // namespace node + +#endif /* GRPC_UV */ diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc new file mode 100644 index 00000000000..cf801e13579 --- /dev/null +++ b/src/node/ext/server_uv.cc @@ -0,0 +1,133 @@ +/* + * + * 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. + * + */ + +#ifdef GRPC_UV + +#include "server.h" + +#include +#include +#include "grpc/grpc.h" +#include "grpc/support/time.h" + +#include "call.h" +#include "completion_queue.h" + +namespace grpc { +namespace node { + +using Nan::Callback; + +using v8::External; +using v8::Function; +using v8::FunctionTemplate; +using v8::Local; +using v8::MaybeLocal; +using v8::Object; +using v8::Value; + +static Callback *shutdown_callback = NULL; + +class ServerShutdownOp : public Op { + public: + ServerShutdownOp(grpc_server *server): server(server) { + } + + ~ServerShutdownOp() { + } + + Local GetNodeValue() const { + return Nan::New(reinterpret_cast(server)); + } + + bool ParseOp(Local value, grpc_op *out, + shared_ptr resources) { + return true; + } + bool IsFinalOp() { + return false; + } + + grpc_server *server; + + protected: + std::string GetTypeString() const { return "shutdown"; } +}; + +Server::Server(grpc_server *server) : wrapped_server(server) { +} + +Server::~Server() { + this->ShutdownServer(); +} + +NAN_METHOD(ServerShutdownCallback) { + if (!info[0]->IsNull()) { + return Nan::ThrowError("forceShutdown failed somehow"); + } + MaybeLocal maybe_result = Nan::To(info[1]); + Local result = maybe_result.ToLocalChecked(); + Local server_val = Nan::Get( + result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked(); + Local server_extern = server_val.As(); + grpc_server *server = reinterpret_cast(server_extern->Value()); + grpc_server_destroy(server); +} + +void Server::ShutdownServer() { + if (this->wrapped_server != NULL) { + if (shutdown_callback == NULL) { + Localcallback_tpl = + Nan::New(ServerShutdownCallback); + shutdown_callback = new Callback( + Nan::GetFunction(callback_tpl).ToLocalChecked()); + } + + ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server); + unique_ptr ops(new OpVec()); + ops->push_back(unique_ptr(op)); + + grpc_server_shutdown_and_notify( + this->wrapped_server, GetCompletionQueue(), + new struct tag(new Callback(**shutdown_callback), ops.release(), + shared_ptr(nullptr), NULL)); + grpc_server_cancel_all_calls(this->wrapped_server); + CompletionQueueNext(); + this->wrapped_server = NULL; + } +} + +} // namespace grpc +} // namespace node + +#endif /* GRPC_UV */ From 626fb455acb45f200a1b933fb63d610b42fb198b Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Fri, 17 Feb 2017 22:52:27 -0800 Subject: [PATCH 06/14] Add Python3.6 to build artifacts --- .../grpc_artifact_python_manylinux_x64/Dockerfile | 1 + .../grpc_artifact_python_manylinux_x86/Dockerfile | 1 + tools/run_tests/artifacts/artifact_targets.py | 14 ++++++++++++-- tools/run_tests/dockerize/build_and_run_docker.sh | 7 +++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile index 69e624aa41a..71098629112 100644 --- a/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile @@ -53,6 +53,7 @@ RUN /opt/python/cp27-cp27m/bin/pip install cython RUN /opt/python/cp27-cp27mu/bin/pip install cython RUN /opt/python/cp34-cp34m/bin/pip install cython RUN /opt/python/cp35-cp35m/bin/pip install cython +RUN /opt/python/cp36-cp36m/bin/pip install cython #################################################### # Install auditwheel with fix for namespace packages diff --git a/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile index 9af80078edd..36286bca53d 100644 --- a/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile @@ -53,6 +53,7 @@ RUN /opt/python/cp27-cp27m/bin/pip install cython RUN /opt/python/cp27-cp27mu/bin/pip install cython RUN /opt/python/cp34-cp34m/bin/pip install cython RUN /opt/python/cp35-cp35m/bin/pip install cython +RUN /opt/python/cp36-cp36m/bin/pip install cython #################################################### # Install auditwheel with fix for namespace packages diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py index 005d99790ad..8648ceb1f3d 100644 --- a/tools/run_tests/artifacts/artifact_targets.py +++ b/tools/run_tests/artifacts/artifact_targets.py @@ -40,7 +40,8 @@ import python_utils.jobset as jobset def create_docker_jobspec(name, dockerfile_dir, shell_command, environ={}, - flake_retries=0, timeout_retries=0, timeout_seconds=30*60): + flake_retries=0, timeout_retries=0, timeout_seconds=30*60, + docker_base_image=None): """Creates jobspec for a task running under docker.""" environ = environ.copy() environ['RUN_COMMAND'] = shell_command @@ -51,6 +52,9 @@ def create_docker_jobspec(name, dockerfile_dir, shell_command, environ={}, docker_env = {'DOCKERFILE_DIR': dockerfile_dir, 'DOCKER_RUN_SCRIPT': 'tools/run_tests/dockerize/docker_run.sh', 'OUTPUT_DIR': 'artifacts'} + + if docker_base_image is not None: + docker_env['DOCKER_BASE_IMAGE'] = docker_base_image jobspec = jobset.JobSpec( cmdline=['tools/run_tests/dockerize/build_and_run_docker.sh'] + docker_args, environ=docker_env, @@ -116,7 +120,8 @@ class PythonArtifact: 'tools/dockerfile/grpc_artifact_python_manylinux_%s' % self.arch, 'tools/run_tests/artifacts/build_artifact_python.sh', environ=environ, - timeout_seconds=60*60) + timeout_seconds=60*60, + docker_base_image='quay.io/pypa/manylinux1_i686' if self.arch == 'x86' else 'quay.io/pypa/manylinux1_x86_64') elif self.platform == 'windows': if 'Python27' in self.py_version or 'Python34' in self.py_version: environ['EXT_COMPILER'] = 'mingw32' @@ -336,19 +341,24 @@ def targets(): PythonArtifact('linux', 'x86', 'cp27-cp27mu'), PythonArtifact('linux', 'x86', 'cp34-cp34m'), PythonArtifact('linux', 'x86', 'cp35-cp35m'), + PythonArtifact('linux', 'x86', 'cp36-cp36m'), PythonArtifact('linux', 'x64', 'cp27-cp27m'), PythonArtifact('linux', 'x64', 'cp27-cp27mu'), PythonArtifact('linux', 'x64', 'cp34-cp34m'), PythonArtifact('linux', 'x64', 'cp35-cp35m'), + PythonArtifact('linux', 'x64', 'cp36-cp36m'), PythonArtifact('macos', 'x64', 'python2.7'), PythonArtifact('macos', 'x64', 'python3.4'), PythonArtifact('macos', 'x64', 'python3.5'), + PythonArtifact('macos', 'x64', 'python3.6'), PythonArtifact('windows', 'x86', 'Python27_32bits'), PythonArtifact('windows', 'x86', 'Python34_32bits'), PythonArtifact('windows', 'x86', 'Python35_32bits'), + PythonArtifact('windows', 'x86', 'Python36_32bits'), PythonArtifact('windows', 'x64', 'Python27'), PythonArtifact('windows', 'x64', 'Python34'), PythonArtifact('windows', 'x64', 'Python35'), + PythonArtifact('windows', 'x64', 'Python36'), RubyArtifact('linux', 'x86'), RubyArtifact('linux', 'x64'), RubyArtifact('macos', 'x64'), diff --git a/tools/run_tests/dockerize/build_and_run_docker.sh b/tools/run_tests/dockerize/build_and_run_docker.sh index f52f16ebd68..8c25c861c1a 100755 --- a/tools/run_tests/dockerize/build_and_run_docker.sh +++ b/tools/run_tests/dockerize/build_and_run_docker.sh @@ -42,11 +42,18 @@ cd - # DOCKER_RUN_SCRIPT - Script to run under docker (relative to grpc repo root) # OUTPUT_DIR - Directory that will be copied from inside docker after finishing. # DOCKERHUB_ORGANIZATION - If set, pull a prebuilt image from given dockerhub org. +# DOCKER_BASE_IMAGE - If set, pull the latest base image. # $@ - Extra args to pass to docker run # Use image name based on Dockerfile location checksum DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) +# Pull the base image to force an update +if [ "$DOCKER_BASE_IMAGE" != "" ] +then + docker pull $DOCKER_BASE_IMAGE +fi + if [ "$DOCKERHUB_ORGANIZATION" != "" ] then DOCKER_IMAGE_NAME=$DOCKERHUB_ORGANIZATION/$DOCKER_IMAGE_NAME From 23f777df084f15df8d0aac3684c5f5c88399c44d Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 22 Feb 2017 23:32:26 -0800 Subject: [PATCH 07/14] When there is an error from filters (such as max recv message size too large), add an error to the batch to avoid emitting new rpc on the server side in C++. --- src/core/lib/surface/call.c | 17 +++++++++++------ src/core/lib/surface/server.c | 3 ++- src/proto/grpc/testing/echo_messages.proto | 1 + test/cpp/end2end/end2end_test.cc | 3 +-- test/cpp/end2end/test_service_impl.cc | 4 ++++ 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 3c563bcc6fa..af32c5b3787 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -112,7 +112,7 @@ static received_status unpack_received_status(gpr_atm atm) { .error = (grpc_error *)(atm & ~(gpr_atm)1)}; } -#define MAX_ERRORS_PER_BATCH 3 +#define MAX_ERRORS_PER_BATCH 4 typedef struct batch_control { grpc_call *call; @@ -254,7 +254,7 @@ static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call, static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl); static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl); static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, - grpc_error *error); + grpc_error *error, bool has_cancelled); static void add_init_error(grpc_error **composite, grpc_error *new) { if (new == GRPC_ERROR_NONE) return; @@ -1223,6 +1223,11 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_call *call = bctl->call; gpr_mu_lock(&bctl->call->mu); if (error != GRPC_ERROR_NONE) { + if (call->receiving_stream != NULL) { + grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); + call->receiving_stream = NULL; + } + add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), true); cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); } @@ -1289,10 +1294,10 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx, } static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, - grpc_error *error) { + grpc_error *error, bool has_cancelled) { if (error == GRPC_ERROR_NONE) return; int idx = (int)gpr_atm_no_barrier_fetch_add(&bctl->num_errors, 1); - if (idx == 0) { + if (idx == 0 && !has_cancelled) { cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE, GRPC_ERROR_REF(error)); } @@ -1306,7 +1311,7 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, gpr_mu_lock(&call->mu); - add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error)); + add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { grpc_metadata_batch *md = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; @@ -1343,7 +1348,7 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; - add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error)); + add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false); finish_batch_step(exec_ctx, bctl); } diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 7210c69fb0d..fdb230b3e20 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -540,7 +540,8 @@ static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), grpc_schedule_on_exec_ctx); - grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, error); + grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, + GRPC_ERROR_REF(error)); return; } diff --git a/src/proto/grpc/testing/echo_messages.proto b/src/proto/grpc/testing/echo_messages.proto index b405acf0431..efb6f4d4935 100644 --- a/src/proto/grpc/testing/echo_messages.proto +++ b/src/proto/grpc/testing/echo_messages.proto @@ -50,6 +50,7 @@ message RequestParams { bool skip_cancelled_check = 9; string expected_transport_security_type = 10; DebugInfo debug_info = 11; + bool server_die = 12; // Server should not see a request with this set. } message EchoRequest { diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 47e5c5bd771..df78557c437 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -901,8 +901,7 @@ TEST_P(End2endTest, RpcMaxMessageSize) { EchoRequest request; EchoResponse response; request.set_message(string(kMaxMessageSize_ * 2, 'a')); - // cancelled is not guaranteed to appear before the end of the service handler - request.mutable_param()->set_skip_cancelled_check(true); + request.mutable_param()->set_server_die(true); ClientContext context; Status s = stub_->Echo(&context, request, &response); diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 001047778d7..59d36e9cb56 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -88,6 +88,10 @@ void CheckServerAuthContext( Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) { + if (request->has_param() && request->param().server_die()) { + gpr_log(GPR_ERROR, "The request should not reach application handler."); + GPR_ASSERT(0); + } int server_try_cancel = GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); if (server_try_cancel > DO_NOT_CANCEL) { From 990d9fe1460d0f274857a5aaa8fe28f4b3852d9b Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Sun, 26 Feb 2017 16:54:18 -0800 Subject: [PATCH 08/14] Client-side keepalive ping Based on soltanmm-google's #9114 --- CMakeLists.txt | 2 + Makefile | 2 + include/grpc/impl/codegen/grpc_types.h | 10 + .../chttp2/transport/chttp2_transport.c | 140 ++++ .../ext/transport/chttp2/transport/internal.h | 23 + test/core/end2end/end2end_nosec_tests.c | 8 + test/core/end2end/end2end_tests.c | 8 + test/core/end2end/gen_build_yaml.py | 1 + test/core/end2end/generate_tests.bzl | 1 + test/core/end2end/tests/keepalive_timeout.c | 240 +++++++ .../generated/sources_and_headers.json | 2 + tools/run_tests/generated/tests.json | 666 +++++++++++++++++- .../end2end_nosec_tests.vcxproj | 2 + .../end2end_nosec_tests.vcxproj.filters | 3 + .../tests/end2end_tests/end2end_tests.vcxproj | 2 + .../end2end_tests.vcxproj.filters | 3 + 16 files changed, 1104 insertions(+), 9 deletions(-) create mode 100644 test/core/end2end/tests/keepalive_timeout.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 383d575a343..483a3db0580 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3788,6 +3788,7 @@ add_library(end2end_tests test/core/end2end/tests/hpack_size.c test/core/end2end/tests/idempotent_request.c test/core/end2end/tests/invoke_large_request.c + test/core/end2end/tests/keepalive_timeout.c test/core/end2end/tests/large_metadata.c test/core/end2end/tests/load_reporting_hook.c test/core/end2end/tests/max_concurrent_streams.c @@ -3877,6 +3878,7 @@ add_library(end2end_nosec_tests test/core/end2end/tests/hpack_size.c test/core/end2end/tests/idempotent_request.c test/core/end2end/tests/invoke_large_request.c + test/core/end2end/tests/keepalive_timeout.c test/core/end2end/tests/large_metadata.c test/core/end2end/tests/load_reporting_hook.c test/core/end2end/tests/max_concurrent_streams.c diff --git a/Makefile b/Makefile index 0e1bcd2c375..50625f1fe07 100644 --- a/Makefile +++ b/Makefile @@ -7692,6 +7692,7 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/hpack_size.c \ test/core/end2end/tests/idempotent_request.c \ test/core/end2end/tests/invoke_large_request.c \ + test/core/end2end/tests/keepalive_timeout.c \ test/core/end2end/tests/large_metadata.c \ test/core/end2end/tests/load_reporting_hook.c \ test/core/end2end/tests/max_concurrent_streams.c \ @@ -7780,6 +7781,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/hpack_size.c \ test/core/end2end/tests/idempotent_request.c \ test/core/end2end/tests/invoke_large_request.c \ + test/core/end2end/tests/keepalive_timeout.c \ test/core/end2end/tests/large_metadata.c \ test/core/end2end/tests/load_reporting_hook.c \ test/core/end2end/tests/max_concurrent_streams.c \ diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index da936bf0281..e5c731304cd 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -193,6 +193,16 @@ typedef struct { /** How much data are we willing to queue up per stream if GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */ #define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size" +/** After a duration of this time the client pings the server to see if the + transport is still alive. Int valued, seconds. */ +#define GRPC_ARG_HTTP2_KEEPALIVE_TIME "grpc.http2.keepalive_time" +/** After waiting for a duration of this time, if the client does not receive + the ping ack, it will close the transport. Int valued, seconds. */ +#define GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT "grpc.http2.keepalive_timeout" +/** Is it permissible to send keepalive pings without any outstanding streams. + Int valued, 0(false)/1(true). */ +#define GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS \ + "grpc.http2.keepalive_permit_without_calls" /** Default authority to pass if none specified on call construction. A string. * */ #define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority" diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 28a31668328..10dc6e6ff6f 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -48,16 +48,19 @@ #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/http2_errors.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" +#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport_impl.h" #define DEFAULT_WINDOW 65535 @@ -66,6 +69,10 @@ #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024) #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) +#define DEFAULT_KEEPALIVE_TIME_SECOND INT_MAX +#define DEFAULT_KEEPALIVE_TIMEOUT_SECOND 20 +#define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false + #define MAX_CLIENT_STREAM_ID 0x7fffffffu int grpc_http_trace = 0; int grpc_flowctl_trace = 0; @@ -139,6 +146,14 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, #define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0 #define DEFAULT_MAX_PINGS_BETWEEN_DATA 3 +/** keepalive-relevant functions */ +static void keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void keepalive_ping_ack_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); + /******************************************************************************* * CONSTRUCTION/DESTRUCTION/REFCOUNTING */ @@ -209,6 +224,73 @@ void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, void grpc_chttp2_ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); } #endif +static void keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); + if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING; + GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); + t->keepalive_ping_id = send_ping_locked( + exec_ctx, t, + grpc_closure_create(keepalive_ping_ack_locked, t, + grpc_combiner_scheduler(t->combiner, false))); + if (t->keepalive_permit_without_calls || t->stream_map.count > 0) + GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog"); + grpc_timer_init( + exec_ctx, &t->keepalive_watchdog_timer, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout), + grpc_closure_create(keepalive_watchdog_fired_locked, t, + grpc_combiner_scheduler(t->combiner, false)), + gpr_now(GPR_CLOCK_MONOTONIC)); + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping"); +} + +static void keepalive_ping_ack_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { + if (error == GRPC_ERROR_NONE) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; + t->keepalive_ping_id = NULL; + grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer); + GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping"); + grpc_timer_init( + exec_ctx, &t->keepalive_ping_timer, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), + grpc_closure_create(keepalive_ping_locked, t, + grpc_combiner_scheduler(t->combiner, false)), + gpr_now(GPR_CLOCK_MONOTONIC)); + } + } else { + GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_DYING); + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end"); +} + +static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { + if (error == GRPC_ERROR_NONE) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; + if (t->keepalive_ping_id != NULL) { + grpc_chttp2_ack_ping(exec_ctx, t, t->keepalive_ping_id); + } + close_transport_locked(exec_ctx, t, + GRPC_ERROR_CREATE("keepalive watchdog timeout")); + } + } else { + // GRPC_LOG_IF_ERROR("keepalive_watchdog", error); + if (error != GRPC_ERROR_CANCELLED) { + gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", + t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); + } + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog"); +} + static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const grpc_channel_args *channel_args, grpc_endpoint *ep, bool is_client) { @@ -316,6 +398,13 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN), }; + /* client-side keepalive setting */ + t->keepalive_time = + gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN); + t->keepalive_timeout = + gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND, GPR_TIMESPAN); + t->keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; + if (channel_args) { for (i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, @@ -363,6 +452,29 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) { t->enable_bdp_probe = grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){1, 0, 1}); + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_KEEPALIVE_TIME)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], + (grpc_integer_options){DEFAULT_KEEPALIVE_TIME_SECOND, 1, INT_MAX}); + t->keepalive_time = value == INT_MAX + ? gpr_inf_future(GPR_TIMESPAN) + : gpr_time_from_seconds(value, GPR_TIMESPAN); + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], + (grpc_integer_options){DEFAULT_KEEPALIVE_TIMEOUT_SECOND, 0, + INT_MAX}); + t->keepalive_timeout = value == INT_MAX + ? gpr_inf_future(GPR_TIMESPAN) + : gpr_time_from_seconds(value, GPR_TIMESPAN); + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { + t->keepalive_permit_without_calls = + (uint32_t)grpc_channel_arg_get_integer( + &channel_args->args[i], + (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE}); } else { static const struct { const char *channel_arg_name; @@ -414,6 +526,18 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; + // Start client-side keepalive pings + if (t->is_client) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; + GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping"); + grpc_timer_init( + exec_ctx, &t->keepalive_ping_timer, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), + grpc_closure_create(keepalive_ping_locked, t, + grpc_combiner_scheduler(t->combiner, false)), + gpr_now(GPR_CLOCK_MONOTONIC)); + } + grpc_chttp2_initiate_write(exec_ctx, t, false, "init"); post_benign_reclaimer(exec_ctx, t); } @@ -458,6 +582,22 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error)); + if (t->is_client) { + switch (t->keepalive_state) { + case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: { + grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); + break; + } + case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING: { + grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); + grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer); + break; + } + case GRPC_CHTTP2_KEEPALIVE_STATE_DYING: { + break; + } + } + } /* flush writable stream list to avoid dangling references */ grpc_chttp2_stream *s; diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 5d41f4bfda6..7fcab0a7223 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -50,6 +50,7 @@ #include "src/core/ext/transport/chttp2/transport/stream_map.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/bdp_estimator.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/pid_controller.h" @@ -208,6 +209,12 @@ struct grpc_chttp2_incoming_byte_stream { grpc_closure finished_action; }; +typedef enum { + GRPC_CHTTP2_KEEPALIVE_STATE_WAITING, + GRPC_CHTTP2_KEEPALIVE_STATE_PINGING, + GRPC_CHTTP2_KEEPALIVE_STATE_DYING, +} grpc_chttp2_keepalive_state; + struct grpc_chttp2_transport { grpc_transport base; /* must be first */ gpr_refcount refs; @@ -382,6 +389,22 @@ struct grpc_chttp2_transport { grpc_closure benign_reclaimer_locked; /** destructive cleanup closure */ grpc_closure destructive_reclaimer_locked; + + /* keep-alive ping support */ + /** timer to initiate ping events */ + grpc_timer keepalive_ping_timer; + /** watchdog to kill the transport when waiting for the keepalive ping */ + grpc_timer keepalive_watchdog_timer; + /** time duration in between pings */ + gpr_timespec keepalive_time; + /** grace period for a ping to complete before watchdog kicks in */ + gpr_timespec keepalive_timeout; + /** if keepalive pings are allowed when there's no outstanding streams */ + bool keepalive_permit_without_calls; + /** keep-alive state machine state */ + grpc_chttp2_keepalive_state keepalive_state; + + uint8_t *keepalive_ping_id; }; typedef enum { diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index fdfa31b5fb7..b351bdee277 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -89,6 +89,8 @@ extern void idempotent_request(grpc_end2end_test_config config); extern void idempotent_request_pre_init(void); extern void invoke_large_request(grpc_end2end_test_config config); extern void invoke_large_request_pre_init(void); +extern void keepalive_timeout(grpc_end2end_test_config config); +extern void keepalive_timeout_pre_init(void); extern void large_metadata(grpc_end2end_test_config config); extern void large_metadata_pre_init(void); extern void load_reporting_hook(grpc_end2end_test_config config); @@ -168,6 +170,7 @@ void grpc_end2end_tests_pre_init(void) { hpack_size_pre_init(); idempotent_request_pre_init(); invoke_large_request_pre_init(); + keepalive_timeout_pre_init(); large_metadata_pre_init(); load_reporting_hook_pre_init(); max_concurrent_streams_pre_init(); @@ -225,6 +228,7 @@ void grpc_end2end_tests(int argc, char **argv, hpack_size(config); idempotent_request(config); invoke_large_request(config); + keepalive_timeout(config); large_metadata(config); load_reporting_hook(config); max_concurrent_streams(config); @@ -343,6 +347,10 @@ void grpc_end2end_tests(int argc, char **argv, invoke_large_request(config); continue; } + if (0 == strcmp("keepalive_timeout", argv[i])) { + keepalive_timeout(config); + continue; + } if (0 == strcmp("large_metadata", argv[i])) { large_metadata(config); continue; diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index f529d6a8997..199c09ec96a 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -91,6 +91,8 @@ extern void idempotent_request(grpc_end2end_test_config config); extern void idempotent_request_pre_init(void); extern void invoke_large_request(grpc_end2end_test_config config); extern void invoke_large_request_pre_init(void); +extern void keepalive_timeout(grpc_end2end_test_config config); +extern void keepalive_timeout_pre_init(void); extern void large_metadata(grpc_end2end_test_config config); extern void large_metadata_pre_init(void); extern void load_reporting_hook(grpc_end2end_test_config config); @@ -171,6 +173,7 @@ void grpc_end2end_tests_pre_init(void) { hpack_size_pre_init(); idempotent_request_pre_init(); invoke_large_request_pre_init(); + keepalive_timeout_pre_init(); large_metadata_pre_init(); load_reporting_hook_pre_init(); max_concurrent_streams_pre_init(); @@ -229,6 +232,7 @@ void grpc_end2end_tests(int argc, char **argv, hpack_size(config); idempotent_request(config); invoke_large_request(config); + keepalive_timeout(config); large_metadata(config); load_reporting_hook(config); max_concurrent_streams(config); @@ -351,6 +355,10 @@ void grpc_end2end_tests(int argc, char **argv, invoke_large_request(config); continue; } + if (0 == strcmp("keepalive_timeout", argv[i])) { + keepalive_timeout(config); + continue; + } if (0 == strcmp("large_metadata", argv[i])) { large_metadata(config); continue; diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 5071299545c..0c749537e60 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -119,6 +119,7 @@ END2END_TESTS = { 'high_initial_seqno': default_test_options, 'idempotent_request': default_test_options, 'invoke_large_request': default_test_options, + 'keepalive_timeout': default_test_options._replace(proxyable=False), 'large_metadata': default_test_options, 'max_concurrent_streams': default_test_options._replace(proxyable=False), 'max_message_length': default_test_options, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 95c06de73f9..431c6995ba0 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -106,6 +106,7 @@ END2END_TESTS = { 'high_initial_seqno': test_options(), 'idempotent_request': test_options(), 'invoke_large_request': test_options(), + 'keepalive_timeout': test_options(proxyable=False), 'large_metadata': test_options(), 'max_concurrent_streams': test_options(proxyable=False), 'max_message_length': test_options(), diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c new file mode 100644 index 00000000000..40a6bb3db53 --- /dev/null +++ b/test/core/end2end/tests/keepalive_timeout.c @@ -0,0 +1,240 @@ +/* + * + * Copyright 2016, 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. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/support/env.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +/* Client sends a request, server replies with a payload, then waits for the + keepalive watchdog timeouts before returning status. */ +static void test_keepalive_timeout(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_timespec deadline = five_seconds_time(); + + grpc_arg keepalive_args[2]; + keepalive_args[0].type = GRPC_ARG_INTEGER; + keepalive_args[0].key = GRPC_ARG_HTTP2_KEEPALIVE_TIME; + keepalive_args[0].value.integer = 2; + keepalive_args[1].type = GRPC_ARG_INTEGER; + keepalive_args[1].key = GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT; + keepalive_args[1].value.integer = 0; + + grpc_channel_args *client_args = NULL; + client_args = grpc_channel_args_copy_and_add(client_args, keepalive_args, 2); + + grpc_end2end_test_fixture f = + begin_test(config, "keepalive_timeout", client_args, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + 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 = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + cq_verify(cqv); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + 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++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + cq_verify(cqv); + + char *details_str = grpc_slice_to_c_string(details); + char *method_str = grpc_slice_to_c_string(call_details.method); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + + gpr_free(details_str); + gpr_free(method_str); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + grpc_call_destroy(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(response_payload_recv); + + if (client_args != NULL) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +void keepalive_timeout(grpc_end2end_test_config config) { + test_keepalive_timeout(config); +} + +void keepalive_timeout_pre_init(void) {} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8cf282a389b..7dc0b3b2584 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6807,6 +6807,7 @@ "test/core/end2end/tests/hpack_size.c", "test/core/end2end/tests/idempotent_request.c", "test/core/end2end/tests/invoke_large_request.c", + "test/core/end2end/tests/keepalive_timeout.c", "test/core/end2end/tests/large_metadata.c", "test/core/end2end/tests/load_reporting_hook.c", "test/core/end2end/tests/max_concurrent_streams.c", @@ -6878,6 +6879,7 @@ "test/core/end2end/tests/hpack_size.c", "test/core/end2end/tests/idempotent_request.c", "test/core/end2end/tests/invoke_large_request.c", + "test/core/end2end/tests/keepalive_timeout.c", "test/core/end2end/tests/large_metadata.c", "test/core/end2end/tests/load_reporting_hook.c", "test/core/end2end/tests/max_concurrent_streams.c", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 8e843d07c05..35e5863904f 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -5881,6 +5881,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -7010,6 +7033,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -8116,6 +8162,28 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_fakesec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -9148,6 +9216,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -10231,6 +10322,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -11266,6 +11380,25 @@ "linux" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_test", + "platforms": [ + "linux" + ] + }, { "args": [ "large_metadata" @@ -12268,6 +12401,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -13395,6 +13551,30 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -14550,6 +14730,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -15700,6 +15903,30 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_oauth2_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -17812,6 +18039,30 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -18846,7 +19097,7 @@ }, { "args": [ - "large_metadata" + "keepalive_timeout" ], "ci_platforms": [ "windows", @@ -18870,7 +19121,7 @@ }, { "args": [ - "load_reporting_hook" + "large_metadata" ], "ci_platforms": [ "windows", @@ -18894,7 +19145,7 @@ }, { "args": [ - "max_concurrent_streams" + "load_reporting_hook" ], "ci_platforms": [ "windows", @@ -18918,7 +19169,7 @@ }, { "args": [ - "max_message_length" + "max_concurrent_streams" ], "ci_platforms": [ "windows", @@ -18942,7 +19193,7 @@ }, { "args": [ - "negative_deadline" + "max_message_length" ], "ci_platforms": [ "windows", @@ -18966,7 +19217,7 @@ }, { "args": [ - "network_status_change" + "negative_deadline" ], "ci_platforms": [ "windows", @@ -18990,7 +19241,7 @@ }, { "args": [ - "no_op" + "network_status_change" ], "ci_platforms": [ "windows", @@ -19014,7 +19265,7 @@ }, { "args": [ - "payload" + "no_op" ], "ci_platforms": [ "windows", @@ -19038,7 +19289,31 @@ }, { "args": [ - "ping_pong_streaming" + "payload" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "ping_pong_streaming" ], "ci_platforms": [ "windows", @@ -19892,6 +20167,32 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -21021,6 +21322,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -22150,6 +22474,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_cert_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -24262,6 +24609,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -25368,6 +25738,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -26474,6 +26867,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -27509,6 +27925,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -28569,6 +29008,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -29585,6 +30047,25 @@ "linux" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_nosec_test", + "platforms": [ + "linux" + ] + }, { "args": [ "large_metadata" @@ -30564,6 +31045,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -31667,6 +32171,30 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -32799,6 +33327,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -34837,6 +35388,30 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -35845,6 +36420,30 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -36867,6 +37466,32 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" @@ -37948,6 +38573,29 @@ "posix" ] }, + { + "args": [ + "keepalive_timeout" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "large_metadata" diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj index 6506f24d1bb..08b3acd03cd 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj @@ -199,6 +199,8 @@ + + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters index 77e5ebf8b19..3a8670c1fae 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters @@ -73,6 +73,9 @@ test\core\end2end\tests + + test\core\end2end\tests + test\core\end2end\tests diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj index 176e8f71976..96418c3ca54 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj @@ -201,6 +201,8 @@ + + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters index fa702679338..cf40abef436 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters @@ -76,6 +76,9 @@ test\core\end2end\tests + + test\core\end2end\tests + test\core\end2end\tests From efdf5a3903f58e4b81cff195c12eefbeef0c257b Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Sun, 26 Feb 2017 23:29:54 -0800 Subject: [PATCH 09/14] Update with the new ping implementation --- .../chttp2/transport/chttp2_transport.c | 170 ++++++++++-------- .../ext/transport/chttp2/transport/internal.h | 2 + test/core/end2end/tests/keepalive_timeout.c | 8 +- 3 files changed, 101 insertions(+), 79 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 10dc6e6ff6f..f9ee71fb119 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -147,10 +147,12 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, #define DEFAULT_MAX_PINGS_BETWEEN_DATA 3 /** keepalive-relevant functions */ -static void keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); -static void keepalive_ping_ack_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); +static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); @@ -224,73 +226,6 @@ void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, void grpc_chttp2_ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); } #endif -static void keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_chttp2_transport *t = arg; - GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); - if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) { - t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING; - GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); - t->keepalive_ping_id = send_ping_locked( - exec_ctx, t, - grpc_closure_create(keepalive_ping_ack_locked, t, - grpc_combiner_scheduler(t->combiner, false))); - if (t->keepalive_permit_without_calls || t->stream_map.count > 0) - GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog"); - grpc_timer_init( - exec_ctx, &t->keepalive_watchdog_timer, - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout), - grpc_closure_create(keepalive_watchdog_fired_locked, t, - grpc_combiner_scheduler(t->combiner, false)), - gpr_now(GPR_CLOCK_MONOTONIC)); - } - GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping"); -} - -static void keepalive_ping_ack_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_chttp2_transport *t = arg; - if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { - if (error == GRPC_ERROR_NONE) { - t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; - t->keepalive_ping_id = NULL; - grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer); - GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping"); - grpc_timer_init( - exec_ctx, &t->keepalive_ping_timer, - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), - grpc_closure_create(keepalive_ping_locked, t, - grpc_combiner_scheduler(t->combiner, false)), - gpr_now(GPR_CLOCK_MONOTONIC)); - } - } else { - GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_DYING); - } - GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end"); -} - -static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_chttp2_transport *t = arg; - if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { - if (error == GRPC_ERROR_NONE) { - t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; - if (t->keepalive_ping_id != NULL) { - grpc_chttp2_ack_ping(exec_ctx, t, t->keepalive_ping_id); - } - close_transport_locked(exec_ctx, t, - GRPC_ERROR_CREATE("keepalive watchdog timeout")); - } - } else { - // GRPC_LOG_IF_ERROR("keepalive_watchdog", error); - if (error != GRPC_ERROR_CANCELLED) { - gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", - t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); - } - } - GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog"); -} - static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const grpc_channel_args *channel_args, grpc_endpoint *ep, bool is_client) { @@ -337,6 +272,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); + grpc_closure_init(&t->start_keepalive_ping_locked, + start_keepalive_ping_locked, t, + grpc_combiner_scheduler(t->combiner, false)); + grpc_closure_init(&t->finish_keepalive_ping_locked, + finish_keepalive_ping_locked, t, + grpc_combiner_scheduler(t->combiner, false)); grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string); t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC); @@ -400,9 +341,14 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, /* client-side keepalive setting */ t->keepalive_time = - gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN); + DEFAULT_KEEPALIVE_TIME_SECOND == INT_MAX + ? gpr_inf_future(GPR_TIMESPAN) + : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN); t->keepalive_timeout = - gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND, GPR_TIMESPAN); + DEFAULT_KEEPALIVE_TIMEOUT_SECOND == INT_MAX + ? gpr_inf_future(GPR_TIMESPAN) + : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND, + GPR_TIMESPAN); t->keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; if (channel_args) { @@ -529,11 +475,11 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, // Start client-side keepalive pings if (t->is_client) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; - GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping"); + GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), - grpc_closure_create(keepalive_ping_locked, t, + grpc_closure_create(init_keepalive_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)), gpr_now(GPR_CLOCK_MONOTONIC)); } @@ -2127,6 +2073,80 @@ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping"); } +static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); + if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) { + if (t->keepalive_permit_without_calls || t->stream_map.count > 0) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING; + GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); + send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, + &t->start_keepalive_ping_locked, + &t->finish_keepalive_ping_locked); + } else { + GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); + grpc_timer_init( + exec_ctx, &t->keepalive_ping_timer, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), + grpc_closure_create(init_keepalive_ping_locked, t, + grpc_combiner_scheduler(t->combiner, false)), + gpr_now(GPR_CLOCK_MONOTONIC)); + } + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping"); +} + +static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog"); + grpc_timer_init( + exec_ctx, &t->keepalive_watchdog_timer, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout), + grpc_closure_create(keepalive_watchdog_fired_locked, t, + grpc_combiner_scheduler(t->combiner, false)), + gpr_now(GPR_CLOCK_MONOTONIC)); +} + +static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { + if (error == GRPC_ERROR_NONE) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; + grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer); + GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); + grpc_timer_init( + exec_ctx, &t->keepalive_ping_timer, + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), + grpc_closure_create(init_keepalive_ping_locked, t, + grpc_combiner_scheduler(t->combiner, false)), + gpr_now(GPR_CLOCK_MONOTONIC)); + } + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end"); +} + +static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; + if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { + if (error == GRPC_ERROR_NONE) { + t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; + close_transport_locked(exec_ctx, t, + GRPC_ERROR_CREATE("keepalive watchdog timeout")); + } + } else { + // The watchdog timer should have been cancelled. + if (error != GRPC_ERROR_CANCELLED) { + gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", + t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); + } + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog"); +} + /******************************************************************************* * CALLBACK LOOP */ diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 7fcab0a7223..0e3e900da09 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -391,6 +391,8 @@ struct grpc_chttp2_transport { grpc_closure destructive_reclaimer_locked; /* keep-alive ping support */ + grpc_closure start_keepalive_ping_locked; + grpc_closure finish_keepalive_ping_locked; /** timer to initiate ping events */ grpc_timer keepalive_ping_timer; /** watchdog to kill the transport when waiting for the keepalive ping */ diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c index 40a6bb3db53..b1f53b17c32 100644 --- a/test/core/end2end/tests/keepalive_timeout.c +++ b/test/core/end2end/tests/keepalive_timeout.c @@ -61,7 +61,7 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, } static gpr_timespec n_seconds_time(int n) { - return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); + return grpc_timeout_seconds_to_deadline(n); } static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } @@ -76,9 +76,9 @@ static void drain_cq(grpc_completion_queue *cq) { static void shutdown_server(grpc_end2end_test_fixture *f) { if (!f->server) return; grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck( - f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) - .type == GRPC_OP_COMPLETE); + GPR_ASSERT( + grpc_completion_queue_pluck(f->cq, tag(1000), five_seconds_time(), NULL) + .type == GRPC_OP_COMPLETE); grpc_server_destroy(f->server); f->server = NULL; } From 28b0f2a0d18533f236c194015a395c22dfb51b3d Mon Sep 17 00:00:00 2001 From: Matt Kwong Date: Mon, 27 Feb 2017 00:52:47 -0800 Subject: [PATCH 10/14] Add tools/internal_ci/ to test filter --- tools/run_tests/python_utils/filter_pull_request_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/run_tests/python_utils/filter_pull_request_tests.py b/tools/run_tests/python_utils/filter_pull_request_tests.py index ca1d6d4eb5a..3734f025d5f 100644 --- a/tools/run_tests/python_utils/filter_pull_request_tests.py +++ b/tools/run_tests/python_utils/filter_pull_request_tests.py @@ -98,6 +98,7 @@ _WHITELIST_DICT = { '^test/distrib/php/': [_PHP_TEST_SUITE], '^test/distrib/python/': [_PYTHON_TEST_SUITE], '^test/distrib/ruby/': [_RUBY_TEST_SUITE], + '^tools/internal_ci/': [], '^vsprojects/': [_WINDOWS_TEST_SUITE], 'binding\.gyp$': [_NODE_TEST_SUITE], 'composer\.json$': [_PHP_TEST_SUITE], From 70e353bf28b080af40539079b798b6e78b09e106 Mon Sep 17 00:00:00 2001 From: Matt Kwong Date: Mon, 27 Feb 2017 00:54:27 -0800 Subject: [PATCH 11/14] Make portability tests pull Docker images from Dockerhub --- tools/internal_ci/linux/grpc_portability_build_only.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/internal_ci/linux/grpc_portability_build_only.sh b/tools/internal_ci/linux/grpc_portability_build_only.sh index 9fac5bcac07..ebdc0e82d76 100644 --- a/tools/internal_ci/linux/grpc_portability_build_only.sh +++ b/tools/internal_ci/linux/grpc_portability_build_only.sh @@ -35,4 +35,7 @@ cd $(dirname $0)/../../.. git submodule update --init +# download docker images from dockerhub +export DOCKERHUB_ORGANIZATION=grpctesting + tools/jenkins/run_jenkins_matrix.sh -f portability linux --build_only From 380a3be6ee11a3795bfbf695b055af033b1f6244 Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Sun, 26 Feb 2017 23:37:50 -0800 Subject: [PATCH 12/14] Add more closures --- .../chttp2/transport/chttp2_transport.c | 20 +++++++++---------- .../ext/transport/chttp2/transport/internal.h | 2 ++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index f9ee71fb119..1cb4e8d8046 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -272,12 +272,17 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); + grpc_closure_init(&t->init_keepalive_ping_locked, init_keepalive_ping_locked, + t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->start_keepalive_ping_locked, start_keepalive_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->finish_keepalive_ping_locked, finish_keepalive_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); + grpc_closure_init(&t->keepalive_watchdog_fired_locked, + keepalive_watchdog_fired_locked, t, + grpc_combiner_scheduler(t->combiner, false)); grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string); t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC); @@ -479,9 +484,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), - grpc_closure_create(init_keepalive_ping_locked, t, - grpc_combiner_scheduler(t->combiner, false)), - gpr_now(GPR_CLOCK_MONOTONIC)); + &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } grpc_chttp2_initiate_write(exec_ctx, t, false, "init"); @@ -2089,9 +2092,7 @@ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), - grpc_closure_create(init_keepalive_ping_locked, t, - grpc_combiner_scheduler(t->combiner, false)), - gpr_now(GPR_CLOCK_MONOTONIC)); + &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping"); @@ -2104,9 +2105,7 @@ static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_timer_init( exec_ctx, &t->keepalive_watchdog_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout), - grpc_closure_create(keepalive_watchdog_fired_locked, t, - grpc_combiner_scheduler(t->combiner, false)), - gpr_now(GPR_CLOCK_MONOTONIC)); + &t->keepalive_watchdog_fired_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, @@ -2138,7 +2137,8 @@ static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, GRPC_ERROR_CREATE("keepalive watchdog timeout")); } } else { - // The watchdog timer should have been cancelled. + // The watchdog timer should have been cancelled by + // finish_keepalive_ping_locked. if (error != GRPC_ERROR_CANCELLED) { gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 0e3e900da09..4a0cfd5a59d 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -391,8 +391,10 @@ struct grpc_chttp2_transport { grpc_closure destructive_reclaimer_locked; /* keep-alive ping support */ + grpc_closure init_keepalive_ping_locked; grpc_closure start_keepalive_ping_locked; grpc_closure finish_keepalive_ping_locked; + grpc_closure keepalive_watchdog_fired_locked; /** timer to initiate ping events */ grpc_timer keepalive_ping_timer; /** watchdog to kill the transport when waiting for the keepalive ping */ From b843ff2ce4b8491b5d9c71bb736142b2f072b395 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 27 Feb 2017 07:34:07 -0800 Subject: [PATCH 13/14] Add more cq benchmarks --- test/cpp/microbenchmarks/bm_cq.cc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc index 195dcef3abd..c017474bf4a 100644 --- a/test/cpp/microbenchmarks/bm_cq.cc +++ b/test/cpp/microbenchmarks/bm_cq.cc @@ -113,6 +113,32 @@ static void BM_Pass1Core(benchmark::State& state) { } BENCHMARK(BM_Pass1Core); +static void BM_Pluck1Core(benchmark::State& state) { + grpc_completion_queue* cq = grpc_completion_queue_create(NULL); + gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); + while (state.KeepRunning()) { + grpc_cq_completion completion; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_cq_begin_op(cq, NULL); + grpc_cq_end_op(&exec_ctx, cq, NULL, GRPC_ERROR_NONE, + DoneWithCompletionOnStack, NULL, &completion); + grpc_exec_ctx_finish(&exec_ctx); + grpc_completion_queue_pluck(cq, NULL, deadline, NULL); + } + grpc_completion_queue_destroy(cq); +} +BENCHMARK(BM_Pluck1Core); + +static void BM_EmptyCore(benchmark::State& state) { + grpc_completion_queue* cq = grpc_completion_queue_create(NULL); + gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC); + while (state.KeepRunning()) { + grpc_completion_queue_next(cq, deadline, NULL); + } + grpc_completion_queue_destroy(cq); +} +BENCHMARK(BM_EmptyCore); + } // namespace testing } // namespace grpc From e0b1e46f0dbd73d56c82dd3fc3066bb182027402 Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Mon, 27 Feb 2017 11:03:07 -0800 Subject: [PATCH 14/14] Address review comments --- .../ext/transport/chttp2/transport/chttp2_transport.c | 9 ++++----- src/core/ext/transport/chttp2/transport/internal.h | 6 ++++-- test/core/end2end/tests/keepalive_timeout.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 1cb4e8d8046..b6b12adedcd 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -424,8 +424,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { t->keepalive_permit_without_calls = (uint32_t)grpc_channel_arg_get_integer( - &channel_args->args[i], - (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE}); + &channel_args->args[i], (grpc_integer_options){0, 0, 1}); } else { static const struct { const char *channel_arg_name; @@ -477,7 +476,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; - // Start client-side keepalive pings + /** Start client-side keepalive pings */ if (t->is_client) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); @@ -2137,8 +2136,8 @@ static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, GRPC_ERROR_CREATE("keepalive watchdog timeout")); } } else { - // The watchdog timer should have been cancelled by - // finish_keepalive_ping_locked. + /** The watchdog timer should have been cancelled by + finish_keepalive_ping_locked. */ if (error != GRPC_ERROR_CANCELLED) { gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 4a0cfd5a59d..d26812ad6be 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -391,9 +391,13 @@ struct grpc_chttp2_transport { grpc_closure destructive_reclaimer_locked; /* keep-alive ping support */ + /** Closure to initialize a keepalive ping */ grpc_closure init_keepalive_ping_locked; + /** Closure to run when the keepalive ping is sent */ grpc_closure start_keepalive_ping_locked; + /** Cousure to run when the keepalive ping ack is received */ grpc_closure finish_keepalive_ping_locked; + /** Closrue to run when the keepalive ping timeouts */ grpc_closure keepalive_watchdog_fired_locked; /** timer to initiate ping events */ grpc_timer keepalive_ping_timer; @@ -407,8 +411,6 @@ struct grpc_chttp2_transport { bool keepalive_permit_without_calls; /** keep-alive state machine state */ grpc_chttp2_keepalive_state keepalive_state; - - uint8_t *keepalive_ping_id; }; typedef enum { diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c index b1f53b17c32..4296be36190 100644 --- a/test/core/end2end/tests/keepalive_timeout.c +++ b/test/core/end2end/tests/keepalive_timeout.c @@ -1,6 +1,6 @@ /* * - * Copyright 2016, Google Inc. + * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without