diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0a7141c1be3..1fcdb6ba53c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,4 +6,3 @@ /cmake/** @jtattermusch @nicolasnoble @apolcyn /src/core/ext/filters/client_channel/** @markdroth @apolcyn @AspirinSJL /tools/dockerfile/** @jtattermusch @apolcyn @nicolasnoble -/tools/run_tests/performance/** @ncteisen @apolcyn @jtattermusch diff --git a/CMakeLists.txt b/CMakeLists.txt index 9813eec7062..7425e62f8f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,6 +257,9 @@ add_dependencies(buildtests_c channel_create_test) add_dependencies(buildtests_c chttp2_hpack_encoder_test) add_dependencies(buildtests_c chttp2_stream_map_test) add_dependencies(buildtests_c chttp2_varint_test) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_c close_fd_test) +endif() add_dependencies(buildtests_c cmdline_test) add_dependencies(buildtests_c combiner_test) add_dependencies(buildtests_c compression_test) @@ -699,6 +702,9 @@ endif() add_dependencies(buildtests_cxx stress_test) add_dependencies(buildtests_cxx thread_manager_test) add_dependencies(buildtests_cxx thread_stress_test) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_cxx time_change_test) +endif() add_dependencies(buildtests_cxx transport_pid_controller_test) add_dependencies(buildtests_cxx transport_security_common_api_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -6302,6 +6308,42 @@ target_link_libraries(chttp2_varint_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(close_fd_test + test/core/bad_connection/close_fd_test.cc +) + + +target_include_directories(close_fd_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(close_fd_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr +) + + # avoid dependency on libstdc++ + if (_gRPC_CORE_NOSTDCXX_FLAGS) + set_target_properties(close_fd_test PROPERTIES LINKER_LANGUAGE C) + target_compile_options(close_fd_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) + endif() + +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) add_executable(cmdline_test test/core/util/cmdline_test.cc @@ -15973,6 +16015,48 @@ target_link_libraries(thread_stress_test ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(time_change_test + test/cpp/end2end/time_change_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(time_change_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(time_change_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + + +endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index b9b7ab4c254..7caf155058a 100644 --- a/Makefile +++ b/Makefile @@ -986,6 +986,7 @@ chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer +close_fd_test: $(BINDIR)/$(CONFIG)/close_fd_test cmdline_test: $(BINDIR)/$(CONFIG)/cmdline_test combiner_test: $(BINDIR)/$(CONFIG)/combiner_test compression_test: $(BINDIR)/$(CONFIG)/compression_test @@ -1248,6 +1249,7 @@ streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test stress_test: $(BINDIR)/$(CONFIG)/stress_test thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test +time_change_test: $(BINDIR)/$(CONFIG)/time_change_test transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test transport_security_common_api_test: $(BINDIR)/$(CONFIG)/transport_security_common_api_test writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test @@ -1450,6 +1452,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \ + $(BINDIR)/$(CONFIG)/close_fd_test \ $(BINDIR)/$(CONFIG)/cmdline_test \ $(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/compression_test \ @@ -1756,6 +1759,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/stress_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ + $(BINDIR)/$(CONFIG)/time_change_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ $(BINDIR)/$(CONFIG)/transport_security_common_api_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ @@ -1943,6 +1947,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/stress_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ + $(BINDIR)/$(CONFIG)/time_change_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ $(BINDIR)/$(CONFIG)/transport_security_common_api_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ @@ -1988,6 +1993,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_varint_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) + $(E) "[RUN] Testing close_fd_test" + $(Q) $(BINDIR)/$(CONFIG)/close_fd_test || ( echo test close_fd_test failed ; exit 1 ) $(E) "[RUN] Testing cmdline_test" $(Q) $(BINDIR)/$(CONFIG)/cmdline_test || ( echo test cmdline_test failed ; exit 1 ) $(E) "[RUN] Testing combiner_test" @@ -2458,6 +2465,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/thread_manager_test || ( echo test thread_manager_test failed ; exit 1 ) $(E) "[RUN] Testing thread_stress_test" $(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 ) + $(E) "[RUN] Testing time_change_test" + $(Q) $(BINDIR)/$(CONFIG)/time_change_test || ( echo test time_change_test failed ; exit 1 ) $(E) "[RUN] Testing transport_pid_controller_test" $(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 ) $(E) "[RUN] Testing transport_security_common_api_test" @@ -11123,6 +11132,38 @@ endif endif +CLOSE_FD_TEST_SRC = \ + test/core/bad_connection/close_fd_test.cc \ + +CLOSE_FD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLOSE_FD_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/close_fd_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/close_fd_test: $(CLOSE_FD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CLOSE_FD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/close_fd_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/bad_connection/close_fd_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_close_fd_test: $(CLOSE_FD_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CLOSE_FD_TEST_OBJS:.o=.dep) +endif +endif + + CMDLINE_TEST_SRC = \ test/core/util/cmdline_test.cc \ @@ -21025,6 +21066,49 @@ endif endif +TIME_CHANGE_TEST_SRC = \ + test/cpp/end2end/time_change_test.cc \ + +TIME_CHANGE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIME_CHANGE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/time_change_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/time_change_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/time_change_test: $(PROTOBUF_DEP) $(TIME_CHANGE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(TIME_CHANGE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/time_change_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/time_change_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_time_change_test: $(TIME_CHANGE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TIME_CHANGE_TEST_OBJS:.o=.dep) +endif +endif + + TRANSPORT_PID_CONTROLLER_TEST_SRC = \ test/core/transport/pid_controller_test.cc \ diff --git a/build.yaml b/build.yaml index 0946e853d1b..bcd98aaac00 100644 --- a/build.yaml +++ b/build.yaml @@ -2246,6 +2246,21 @@ targets: - test/core/end2end/fuzzers/client_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary maxlen: 2048 +- name: close_fd_test + build: test + language: c + src: + - test/core/bad_connection/close_fd_test.cc + deps: + - grpc_test_util + - grpc + - gpr + exclude_configs: + - tsan + platforms: + - mac + - linux + - posix - name: cmdline_test build: test language: c @@ -5558,6 +5573,22 @@ targets: - grpc++_unsecure - grpc_unsecure - gpr +- name: time_change_test + gtest: true + build: test + language: c++ + src: + - test/cpp/end2end/time_change_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr + platforms: + - mac + - linux + - posix - name: transport_pid_controller_test build: test language: c++ diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index aaeb23694e8..cf760eaad05 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -189,6 +189,8 @@ #define GPR_PLATFORM_STRING "ios" #define GPR_CPU_IPHONE 1 #define GPR_PTHREAD_TLS 1 +/* the c-ares resolver isnt safe to enable on iOS */ +#define GRPC_ARES 0 #else /* TARGET_OS_IPHONE */ #define GPR_PLATFORM_STRING "osx" #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED @@ -520,6 +522,35 @@ typedef unsigned __int64 uint64_t; #define CENSUSAPI GRPCAPI #endif +#ifndef GPR_HAS_ATTRIBUTE +#ifdef __has_attribute +#define GPR_HAS_ATTRIBUTE(a) __has_attribute(a) +#else +#define GPR_HAS_ATTRIBUTE(a) 0 +#endif +#endif /* GPR_HAS_ATTRIBUTE */ + +#ifndef GPR_ATTRIBUTE_NOINLINE +#if GPR_HAS_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define GPR_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define GPR_HAS_ATTRIBUTE_NOINLINE 1 +#else +#define GPR_ATTRIBUTE_NOINLINE +#endif +#endif /* GPR_ATTRIBUTE_NOINLINE */ + +#ifndef GPR_ATTRIBUTE_WEAK +/* Attribute weak is broken on LLVM/windows: + * https://bugs.llvm.org/show_bug.cgi?id=37598 */ +#if (GPR_HAS_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__))) && \ + !(defined(__llvm__) && defined(_WIN32)) +#define GPR_ATTRIBUTE_WEAK __attribute__((weak)) +#define GPR_HAS_ATTRIBUTE_WEAK 1 +#else +#define GPR_ATTRIBUTE_WEAK +#endif +#endif /* GPR_ATTRIBUTE_WEAK */ + #ifndef GPR_ATTRIBUTE_NO_TSAN /* (1) */ #if defined(__has_feature) #if __has_feature(thread_sanitizer) diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index 90dbfd3b1f8..62339daae5e 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -81,8 +81,8 @@ struct grpc_slice { struct grpc_slice_refcount* refcount; union grpc_slice_data { struct grpc_slice_refcounted { - uint8_t* bytes; size_t length; + uint8_t* bytes; } refcounted; struct grpc_slice_inlined { uint8_t length; diff --git a/include/grpcpp/alarm_impl.h b/include/grpcpp/alarm_impl.h index 7844e7c8866..543dcd82a4c 100644 --- a/include/grpcpp/alarm_impl.h +++ b/include/grpcpp/alarm_impl.h @@ -16,8 +16,8 @@ * */ -/// An Alarm posts the user provided tag to its associated completion queue upon -/// expiry or cancellation. +/// An Alarm posts the user-provided tag to its associated completion queue or +/// invokes the user-provided function on expiry or cancellation. #ifndef GRPCPP_ALARM_IMPL_H #define GRPCPP_ALARM_IMPL_H @@ -32,7 +32,6 @@ namespace grpc_impl { -/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h). class Alarm : private ::grpc::GrpcLibraryCodegen { public: /// Create an unset completion queue alarm diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index df68cf31441..885bd8de8d7 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -248,22 +249,15 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { /// the \a sync_server_cqs) std::vector> sync_req_mgrs_; - // Outstanding callback requests. The vector is indexed by method with a list - // per method. Each element should store its own iterator in the list and - // should erase it when the request is actually bound to an RPC. Synchronize - // this list with its own mu_ (not the server mu_) since these must be active - // at Shutdown when the server mu_ is locked. - // TODO(vjpai): Merge with the core request matcher to avoid duplicate work - struct MethodReqList { - std::mutex reqs_mu; - // Maintain our own list size count since list::size is still linear - // for some libraries (supposed to be constant since C++11) - // TODO(vjpai): Remove reqs_list_sz and use list::size when possible - size_t reqs_list_sz{0}; - std::list reqs_list; - using iterator = decltype(reqs_list)::iterator; - }; - std::vector callback_reqs_; + // Outstanding unmatched callback requests, indexed by method. + // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't + // copyable or movable and thus will cause compilation errors. We + // actually only want to extend the vector before the threaded use + // starts, but this is still a limitation. + std::vector callback_unmatched_reqs_count_; + + // List of callback requests to start when server actually starts. + std::list callback_reqs_to_start_; // Server status std::mutex mu_; diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 1d188a655f8..35225b0d5c3 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -405,18 +405,23 @@ class Subchannel::ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); Subchannel* c = self->subchannel_; - MutexLock lock(&c->mu_); - if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { - self->Unref(); - return; - } - if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker_, - self->health_state_, GRPC_ERROR_REF(error), - "health_changed"); + { + MutexLock lock(&c->mu_); + if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN && + self->health_check_client_ != nullptr) { + if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { + grpc_connectivity_state_set(&c->state_and_health_tracker_, + self->health_state_, + GRPC_ERROR_REF(error), "health_changed"); + } + self->health_check_client_->NotifyOnHealthChange( + &self->health_state_, &self->on_health_changed_); + self = nullptr; // So we don't unref below. + } } - self->health_check_client_->NotifyOnHealthChange(&self->health_state_, - &self->on_health_changed_); + // Don't unref until we've released the lock, because this might + // cause the subchannel (which contains the lock) to be destroyed. + if (self != nullptr) self->Unref(); } Subchannel* subchannel_; diff --git a/src/core/ext/transport/chttp2/transport/flow_control.cc b/src/core/ext/transport/chttp2/transport/flow_control.cc index 53932bcb7f5..ee2bb930802 100644 --- a/src/core/ext/transport/chttp2/transport/flow_control.cc +++ b/src/core/ext/transport/chttp2/transport/flow_control.cc @@ -111,7 +111,7 @@ void FlowControlTrace::Finish() { saw_str = gpr_leftpad("", ' ', kTracePadding); } gpr_log(GPR_DEBUG, - "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s", + "%p[%u][%s] | %s | trw:%s, tlw:%s, taw:%s, srw:%s, slw:%s, saw:%s", tfc_, sfc_ != nullptr ? sfc_->stream()->id : 0, tfc_->transport()->is_client ? "cli" : "svr", reason_, trw_str, tlw_str, taw_str, srw_str, slw_str, saw_str); diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc index dbe9df6ae38..9b4c3ce7e11 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc @@ -59,7 +59,7 @@ static grpc_slice_refcount terminal_slice_refcount = {nullptr, nullptr}; static const grpc_slice terminal_slice = { &terminal_slice_refcount, /* refcount */ - {{nullptr, 0}} /* data.refcounted */ + {{0, nullptr}} /* data.refcounted */ }; typedef struct { diff --git a/src/core/lib/gpr/time.cc b/src/core/lib/gpr/time.cc index 64c1c98f560..8927dab5a30 100644 --- a/src/core/lib/gpr/time.cc +++ b/src/core/lib/gpr/time.cc @@ -135,6 +135,10 @@ gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) { gpr_timespec sum; int64_t inc = 0; GPR_ASSERT(b.clock_type == GPR_TIMESPAN); + // tv_nsec in a timespan is always +ve. -ve timespan is represented as (-ve + // tv_sec, +ve tv_nsec). For example, timespan = -2.5 seconds is represented + // as {-3, 5e8, GPR_TIMESPAN} + GPR_ASSERT(b.tv_nsec >= 0); sum.clock_type = a.clock_type; sum.tv_nsec = a.tv_nsec + b.tv_nsec; if (sum.tv_nsec >= GPR_NS_PER_SEC) { @@ -165,6 +169,10 @@ gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) { int64_t dec = 0; if (b.clock_type == GPR_TIMESPAN) { diff.clock_type = a.clock_type; + // tv_nsec in a timespan is always +ve. -ve timespan is represented as (-ve + // tv_sec, +ve tv_nsec). For example, timespan = -2.5 seconds is represented + // as {-3, 5e8, GPR_TIMESPAN} + GPR_ASSERT(b.tv_nsec >= 0); } else { GPR_ASSERT(a.clock_type == b.clock_type); diff.clock_type = GPR_TIMESPAN; diff --git a/src/core/lib/gpr/time_posix.cc b/src/core/lib/gpr/time_posix.cc index 28836bfa54e..1b3e36486fc 100644 --- a/src/core/lib/gpr/time_posix.cc +++ b/src/core/lib/gpr/time_posix.cc @@ -133,12 +133,18 @@ gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl; #ifdef GPR_LOW_LEVEL_COUNTERS gpr_atm gpr_now_call_count; #endif - gpr_timespec gpr_now(gpr_clock_type clock_type) { #ifdef GPR_LOW_LEVEL_COUNTERS __atomic_fetch_add(&gpr_now_call_count, 1, __ATOMIC_RELAXED); #endif - return gpr_now_impl(clock_type); + // validate clock type + GPR_ASSERT(clock_type == GPR_CLOCK_MONOTONIC || + clock_type == GPR_CLOCK_REALTIME || + clock_type == GPR_CLOCK_PRECISE); + gpr_timespec ts = gpr_now_impl(clock_type); + // tv_nsecs must be in the range [0, 1e9). + GPR_ASSERT(ts.tv_nsec >= 0 && ts.tv_nsec < 1e9); + return ts; } void gpr_sleep_until(gpr_timespec until) { diff --git a/src/core/lib/iomgr/buffer_list.h b/src/core/lib/iomgr/buffer_list.h index 215ab03a563..3dba15312d6 100644 --- a/src/core/lib/iomgr/buffer_list.h +++ b/src/core/lib/iomgr/buffer_list.h @@ -148,7 +148,9 @@ class TracedBuffer { public: /* Dummy shutdown function */ static void Shutdown(grpc_core::TracedBuffer** head, void* remaining, - grpc_error* shutdown_err) {} + grpc_error* shutdown_err) { + GRPC_ERROR_UNREF(shutdown_err); + } }; #endif /* GRPC_LINUX_ERRQUEUE */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 0a0891013af..d6947d00e84 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -45,6 +45,7 @@ #include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/block_annotate.h" @@ -78,18 +79,6 @@ typedef enum { PO_MULTI, PO_FD, PO_EMPTY } pollable_type; typedef struct pollable pollable; -typedef struct cached_fd { - // Set to the grpc_fd's salt value. See 'salt' variable' in grpc_fd for more - // details - intptr_t salt; - - // The underlying fd - int fd; - - // A recency time counter that helps to determine the LRU fd in the cache - uint64_t last_used; -} cached_fd; - /// A pollable is something that can be polled: it has an epoll set to poll on, /// and a wakeup fd for kicks /// There are three broad types: @@ -120,33 +109,6 @@ struct pollable { int event_cursor; int event_count; struct epoll_event events[MAX_EPOLL_EVENTS]; - - // We may be calling pollable_add_fd() on the same (pollable, fd) multiple - // times. To prevent pollable_add_fd() from making multiple sys calls to - // epoll_ctl() to add the fd, we maintain a cache of what fds are already - // present in the underlying epoll-set. - // - // Since this is not a correctness issue, we do not need to maintain all the - // fds in the cache. Hence we just use an LRU cache of size 'MAX_FDS_IN_CACHE' - // - // NOTE: An ideal implementation of this should do the following: - // 1) Add fds to the cache in pollable_add_fd() function (i.e whenever the fd - // is added to the pollable's epoll set) - // 2) Remove the fd from the cache whenever the fd is removed from the - // underlying epoll set (i.e whenever fd_orphan() is called). - // - // Implementing (2) above (i.e removing fds from cache on fd_orphan) adds a - // lot of complexity since an fd can be present in multiple pollables. So our - // implementation ONLY DOES (1) and NOT (2). - // - // The cache_fd.salt variable helps here to maintain correctness (it serves as - // an epoch that differentiates one grpc_fd from the other even though both of - // them may have the same fd number) - // - // The following implements LRU-eviction cache of fds in this pollable - cached_fd fd_cache[MAX_FDS_IN_CACHE]; - int fd_cache_size; - uint64_t fd_cache_counter; // Recency timer tick counter }; static const char* pollable_type_string(pollable_type t) { @@ -189,37 +151,86 @@ static void pollable_unref(pollable* p, int line, const char* reason); * Fd Declarations */ -// Monotonically increasing Epoch counter that is assinged to each grpc_fd. See -// the description of 'salt' variable in 'grpc_fd' for more details -// TODO: (sreek/kpayson) gpr_atm is intptr_t which may not be wide-enough on -// 32-bit systems. Change this to int_64 - atleast on 32-bit systems -static gpr_atm g_fd_salt; - struct grpc_fd { - int fd; + grpc_fd(int fd, const char* name, bool track_err) + : fd(fd), track_err(track_err) { + gpr_mu_init(&orphan_mu); + gpr_mu_init(&pollable_mu); + read_closure.InitEvent(); + write_closure.InitEvent(); + error_closure.InitEvent(); + + char* fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&iomgr_object, fd_name); +#ifndef NDEBUG + if (grpc_trace_fd_refcount.enabled()) { + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, this, fd_name); + } +#endif + gpr_free(fd_name); + } + + // This is really the dtor, but the poller threads waking up from + // epoll_wait() may access the (read|write|error)_closure after destruction. + // Since the object will be added to the free pool, this behavior is + // not going to cause issues, except spurious events if the FD is reused + // while the race happens. + void destroy() { + grpc_iomgr_unregister_object(&iomgr_object); + + POLLABLE_UNREF(pollable_obj, "fd_pollable"); + pollsets.clear(); + gpr_mu_destroy(&pollable_mu); + gpr_mu_destroy(&orphan_mu); + + read_closure.DestroyEvent(); + write_closure.DestroyEvent(); + error_closure.DestroyEvent(); + + invalidate(); + } - // Since fd numbers can be reused (after old fds are closed), this serves as - // an epoch that uniquely identifies this fd (i.e the pair (salt, fd) is - // unique (until the salt counter (i.e g_fd_salt) overflows) - intptr_t salt; +#ifndef NDEBUG + /* Since an fd is never really destroyed (i.e gpr_free() is not called), it is + * hard-to-debug cases where fd fields are accessed even after calling + * fd_destroy(). The following invalidates fd fields to make catching such + * errors easier */ + void invalidate() { + fd = -1; + gpr_atm_no_barrier_store(&refst, -1); + memset(&orphan_mu, -1, sizeof(orphan_mu)); + memset(&pollable_mu, -1, sizeof(pollable_mu)); + pollable_obj = nullptr; + on_done_closure = nullptr; + memset(&iomgr_object, -1, sizeof(iomgr_object)); + track_err = false; + } +#else + void invalidate() {} +#endif + + int fd; // refst format: // bit 0 : 1=Active / 0=Orphaned // bits 1-n : refcount // Ref/Unref by two to avoid altering the orphaned bit - gpr_atm refst; + gpr_atm refst = 1; gpr_mu orphan_mu; + // Protects pollable_obj and pollsets. gpr_mu pollable_mu; - pollable* pollable_obj; + grpc_core::InlinedVector pollsets; // Used in PO_MULTI. + pollable* pollable_obj = nullptr; // Used in PO_FD. - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; - grpc_core::ManualConstructor error_closure; + grpc_core::LockfreeEvent read_closure; + grpc_core::LockfreeEvent write_closure; + grpc_core::LockfreeEvent error_closure; - struct grpc_fd* freelist_next; - grpc_closure* on_done_closure; + struct grpc_fd* freelist_next = nullptr; + grpc_closure* on_done_closure = nullptr; grpc_iomgr_object iomgr_object; @@ -258,6 +269,7 @@ struct grpc_pollset_worker { struct grpc_pollset { gpr_mu mu; gpr_atm worker_count; + gpr_atm active_pollable_type; pollable* active_pollable; bool kicked_without_poller; grpc_closure* shutdown_closure; @@ -337,39 +349,10 @@ static void ref_by(grpc_fd* fd, int n) { GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } -#ifndef NDEBUG -#define INVALIDATE_FD(fd) invalidate_fd(fd) -/* Since an fd is never really destroyed (i.e gpr_free() is not called), it is - * hard to cases where fd fields are accessed even after calling fd_destroy(). - * The following invalidates fd fields to make catching such errors easier */ -static void invalidate_fd(grpc_fd* fd) { - fd->fd = -1; - fd->salt = -1; - gpr_atm_no_barrier_store(&fd->refst, -1); - memset(&fd->orphan_mu, -1, sizeof(fd->orphan_mu)); - memset(&fd->pollable_mu, -1, sizeof(fd->pollable_mu)); - fd->pollable_obj = nullptr; - fd->on_done_closure = nullptr; - memset(&fd->iomgr_object, -1, sizeof(fd->iomgr_object)); - fd->track_err = false; -} -#else -#define INVALIDATE_FD(fd) -#endif - /* Uninitialize and add to the freelist */ static void fd_destroy(void* arg, grpc_error* error) { grpc_fd* fd = static_cast(arg); - grpc_iomgr_unregister_object(&fd->iomgr_object); - POLLABLE_UNREF(fd->pollable_obj, "fd_pollable"); - gpr_mu_destroy(&fd->pollable_mu); - gpr_mu_destroy(&fd->orphan_mu); - - fd->read_closure->DestroyEvent(); - fd->write_closure->DestroyEvent(); - fd->error_closure->DestroyEvent(); - - INVALIDATE_FD(fd); + fd->destroy(); /* Add the fd to the freelist */ gpr_mu_lock(&fd_freelist_mu); @@ -429,35 +412,9 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) { if (new_fd == nullptr) { new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); - new_fd->error_closure.Init(); - } - - new_fd->fd = fd; - new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1); - gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); - gpr_mu_init(&new_fd->orphan_mu); - gpr_mu_init(&new_fd->pollable_mu); - new_fd->pollable_obj = nullptr; - new_fd->read_closure->InitEvent(); - new_fd->write_closure->InitEvent(); - new_fd->error_closure->InitEvent(); - new_fd->freelist_next = nullptr; - new_fd->on_done_closure = nullptr; - - char* fd_name; - gpr_asprintf(&fd_name, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); -#ifndef NDEBUG - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name); } -#endif - gpr_free(fd_name); - new_fd->track_err = track_err; - return new_fd; + return new (new_fd) grpc_fd(fd, name, track_err); } static int fd_wrapped_fd(grpc_fd* fd) { @@ -465,6 +422,7 @@ static int fd_wrapped_fd(grpc_fd* fd) { return (gpr_atm_acq_load(&fd->refst) & 1) ? ret_fd : -1; } +static int pollset_epoll_fd_locked(grpc_pollset* pollset); static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, const char* reason) { bool is_fd_closed = false; @@ -475,7 +433,6 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, // true so that the pollable will no longer access its owner_fd field. gpr_mu_lock(&fd->pollable_mu); pollable* pollable_obj = fd->pollable_obj; - gpr_mu_unlock(&fd->pollable_mu); if (pollable_obj) { gpr_mu_lock(&pollable_obj->owner_orphan_mu); @@ -487,6 +444,20 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, /* If release_fd is not NULL, we should be relinquishing control of the file descriptor fd->fd (but we still own the grpc_fd structure). */ if (release_fd != nullptr) { + // Remove the FD from all epolls sets, before releasing it. + // Otherwise, we will receive epoll events after we release the FD. + epoll_event ev_fd; + memset(&ev_fd, 0, sizeof(ev_fd)); + if (release_fd != nullptr) { + if (pollable_obj != nullptr) { // For PO_FD. + epoll_ctl(pollable_obj->epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + for (size_t i = 0; i < fd->pollsets.size(); ++i) { // For PO_MULTI. + grpc_pollset* pollset = fd->pollsets[i]; + const int epfd = pollset_epoll_fd_locked(pollset); + epoll_ctl(epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + } *release_fd = fd->fd; } else { close(fd->fd); @@ -508,40 +479,56 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, gpr_mu_unlock(&pollable_obj->owner_orphan_mu); } + gpr_mu_unlock(&fd->pollable_mu); gpr_mu_unlock(&fd->orphan_mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return fd->read_closure.IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { + if (fd->read_closure.SetShutdown(GRPC_ERROR_REF(why))) { if (shutdown(fd->fd, SHUT_RDWR)) { if (errno != ENOTCONN) { gpr_log(GPR_ERROR, "Error shutting down fd %d. errno: %d", grpc_fd_wrapped_fd(fd), errno); } } - fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); - fd->error_closure->SetShutdown(GRPC_ERROR_REF(why)); + fd->write_closure.SetShutdown(GRPC_ERROR_REF(why)); + fd->error_closure.SetShutdown(GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(closure); + fd->read_closure.NotifyOn(closure); } static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(closure); + fd->write_closure.NotifyOn(closure); } static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { - fd->error_closure->NotifyOn(closure); + fd->error_closure.NotifyOn(closure); +} + +static bool fd_has_pollset(grpc_fd* fd, grpc_pollset* pollset) { + grpc_core::MutexLock lock(&fd->pollable_mu); + for (size_t i = 0; i < fd->pollsets.size(); ++i) { + if (fd->pollsets[i] == pollset) { + return true; + } + } + return false; +} + +static void fd_add_pollset(grpc_fd* fd, grpc_pollset* pollset) { + grpc_core::MutexLock lock(&fd->pollable_mu); + fd->pollsets.push_back(pollset); } /******************************************************************************* @@ -594,8 +581,6 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { (*p)->root_worker = nullptr; (*p)->event_cursor = 0; (*p)->event_count = 0; - (*p)->fd_cache_size = 0; - (*p)->fd_cache_counter = 0; return GRPC_ERROR_NONE; } @@ -637,39 +622,6 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { grpc_error* error = GRPC_ERROR_NONE; static const char* err_desc = "pollable_add_fd"; const int epfd = p->epfd; - gpr_mu_lock(&p->mu); - p->fd_cache_counter++; - - // Handle the case of overflow for our cache counter by - // reseting the recency-counter on all cache objects - if (p->fd_cache_counter == 0) { - for (int i = 0; i < p->fd_cache_size; i++) { - p->fd_cache[i].last_used = 0; - } - } - - int lru_idx = 0; - for (int i = 0; i < p->fd_cache_size; i++) { - if (p->fd_cache[i].fd == fd->fd && p->fd_cache[i].salt == fd->salt) { - GRPC_STATS_INC_POLLSET_FD_CACHE_HITS(); - p->fd_cache[i].last_used = p->fd_cache_counter; - gpr_mu_unlock(&p->mu); - return GRPC_ERROR_NONE; - } else if (p->fd_cache[i].last_used < p->fd_cache[lru_idx].last_used) { - lru_idx = i; - } - } - - // Add to cache - if (p->fd_cache_size < MAX_FDS_IN_CACHE) { - lru_idx = p->fd_cache_size; - p->fd_cache_size++; - } - p->fd_cache[lru_idx].fd = fd->fd; - p->fd_cache[lru_idx].salt = fd->salt; - p->fd_cache[lru_idx].last_used = p->fd_cache_counter; - gpr_mu_unlock(&p->mu); - if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p); } @@ -849,6 +801,7 @@ static grpc_error* pollset_kick_all(grpc_pollset* pollset) { static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { gpr_mu_init(&pollset->mu); gpr_atm_no_barrier_store(&pollset->worker_count, 0); + gpr_atm_no_barrier_store(&pollset->active_pollable_type, PO_EMPTY); pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset"); pollset->kicked_without_poller = false; pollset->shutdown_closure = nullptr; @@ -869,11 +822,11 @@ static int poll_deadline_to_millis_timeout(grpc_millis millis) { return static_cast(delta); } -static void fd_become_readable(grpc_fd* fd) { fd->read_closure->SetReady(); } +static void fd_become_readable(grpc_fd* fd) { fd->read_closure.SetReady(); } -static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } +static void fd_become_writable(grpc_fd* fd) { fd->write_closure.SetReady(); } -static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); } +static void fd_has_errors(grpc_fd* fd) { fd->error_closure.SetReady(); } /* Get the pollable_obj attached to this fd. If none is attached, create a new * pollable object (of type PO_FD), attach it to the fd and return it @@ -1283,6 +1236,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { POLLABLE_UNREF(pollset->active_pollable, "pollset"); pollset->active_pollable = po_at_start; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); POLLABLE_UNREF(po_at_start, "pollset_add_fd"); } return error; @@ -1329,17 +1284,38 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, pollset->active_pollable = po_at_start; *pollable_obj = nullptr; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); *pollable_obj = POLLABLE_REF(pollset->active_pollable, "pollset_set"); POLLABLE_UNREF(po_at_start, "pollset_as_multipollable"); } return error; } +// Caller must hold the lock for `pollset->mu`. +static int pollset_epoll_fd_locked(grpc_pollset* pollset) { + return pollset->active_pollable->epfd; +} + static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { GPR_TIMER_SCOPE("pollset_add_fd", 0); - gpr_mu_lock(&pollset->mu); + + // We never transition from PO_MULTI to other modes (i.e., PO_FD or PO_EMOPTY) + // and, thus, it is safe to simply store and check whether the FD has already + // been added to the active pollable previously. + if (gpr_atm_acq_load(&pollset->active_pollable_type) == PO_MULTI && + fd_has_pollset(fd, pollset)) { + return; + } + + grpc_core::MutexLock lock(&pollset->mu); grpc_error* error = pollset_add_fd_locked(pollset, fd); - gpr_mu_unlock(&pollset->mu); + + // If we are in PO_MULTI mode, we should update the pollsets of the FD. + if (gpr_atm_no_barrier_load(&pollset->active_pollable_type) == PO_MULTI) { + fd_add_pollset(fd, pollset); + } + GRPC_LOG_IF_ERROR("pollset_add_fd", error); } diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 792ffd27385..61db36bd99e 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -195,7 +195,7 @@ static void run_poller(void* bp, grpc_error* error_ignored) { static void drop_uncovered(grpc_tcp* tcp) { backup_poller* p = (backup_poller*)gpr_atm_acq_load(&g_backup_poller); gpr_atm old_count = - gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, -1); + gpr_atm_full_fetch_add(&g_uncovered_notifications_pending, -1); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "BACKUP_POLLER:%p uncover cnt %d->%d", p, static_cast(old_count), static_cast(old_count) - 1); @@ -343,6 +343,13 @@ static void tcp_free(grpc_tcp* tcp) { grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); gpr_free(tcp->peer_string); + /* The lock is not really necessary here, since all refs have been released */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; gpr_mu_destroy(&tcp->tb_mu); gpr_free(tcp); } @@ -389,12 +396,6 @@ static void tcp_destroy(grpc_endpoint* ep) { grpc_tcp* tcp = reinterpret_cast(ep); grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); if (grpc_event_engine_can_track_errors()) { - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } @@ -1184,12 +1185,6 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); if (grpc_event_engine_can_track_errors()) { /* Stop errors notification. */ - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } diff --git a/src/core/lib/security/credentials/alts/alts_credentials.cc b/src/core/lib/security/credentials/alts/alts_credentials.cc index 06546492bc7..9a337903063 100644 --- a/src/core/lib/security/credentials/alts/alts_credentials.cc +++ b/src/core/lib/security/credentials/alts/alts_credentials.cc @@ -31,7 +31,7 @@ #include "src/core/lib/security/security_connector/alts/alts_security_connector.h" #define GRPC_CREDENTIALS_TYPE_ALTS "Alts" -#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal:8080" +#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal.:8080" grpc_alts_credentials::grpc_alts_credentials( const grpc_alts_credentials_options* options, diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h index 4fb7ed85e70..a9d581280d1 100644 --- a/src/core/lib/security/credentials/credentials.h +++ b/src/core/lib/security/credentials/credentials.h @@ -60,7 +60,7 @@ typedef enum { #define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 -#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal" +#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal." #define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ "/computeMetadata/v1/instance/service-accounts/default/token" diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index a63bd5c0e56..aa57fa2c5ec 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -46,7 +46,7 @@ /* -- Constants. -- */ -#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" +#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal." /* -- Default credentials. -- */ diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 426a4a3f24e..f473b23788e 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -854,15 +854,11 @@ static void cq_end_op_for_callback( // for reserved storage. Invoke the done callback right away to release it. done(done_arg, storage); - gpr_mu_lock(cq->mu); - cq_check_tag(cq, tag, false); /* Used in debug builds only */ + cq_check_tag(cq, tag, true); /* Used in debug builds only */ gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1); if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { - gpr_mu_unlock(cq->mu); cq_finish_shutdown_callback(cq); - } else { - gpr_mu_unlock(cq->mu); } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/transport/static_metadata.cc b/src/core/lib/transport/static_metadata.cc index 3dfaaaad5c8..963626a9dc9 100644 --- a/src/core/lib/transport/static_metadata.cc +++ b/src/core/lib/transport/static_metadata.cc @@ -236,113 +236,113 @@ grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = { }; const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = { - {&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[3], {{g_bytes + 19, 10}}}, - {&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[5], {{g_bytes + 36, 2}}}, - {&grpc_static_metadata_refcounts[6], {{g_bytes + 38, 12}}}, - {&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[8], {{g_bytes + 61, 16}}}, - {&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[11], {{g_bytes + 110, 21}}}, - {&grpc_static_metadata_refcounts[12], {{g_bytes + 131, 13}}}, - {&grpc_static_metadata_refcounts[13], {{g_bytes + 144, 14}}}, - {&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[17], {{g_bytes + 201, 30}}}, - {&grpc_static_metadata_refcounts[18], {{g_bytes + 231, 37}}}, - {&grpc_static_metadata_refcounts[19], {{g_bytes + 268, 10}}}, - {&grpc_static_metadata_refcounts[20], {{g_bytes + 278, 4}}}, - {&grpc_static_metadata_refcounts[21], {{g_bytes + 282, 8}}}, - {&grpc_static_metadata_refcounts[22], {{g_bytes + 290, 26}}}, - {&grpc_static_metadata_refcounts[23], {{g_bytes + 316, 22}}}, - {&grpc_static_metadata_refcounts[24], {{g_bytes + 338, 12}}}, - {&grpc_static_metadata_refcounts[25], {{g_bytes + 350, 1}}}, - {&grpc_static_metadata_refcounts[26], {{g_bytes + 351, 1}}}, - {&grpc_static_metadata_refcounts[27], {{g_bytes + 352, 1}}}, - {&grpc_static_metadata_refcounts[28], {{g_bytes + 353, 1}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}, - {&grpc_static_metadata_refcounts[30], {{g_bytes + 354, 19}}}, - {&grpc_static_metadata_refcounts[31], {{g_bytes + 373, 12}}}, - {&grpc_static_metadata_refcounts[32], {{g_bytes + 385, 30}}}, - {&grpc_static_metadata_refcounts[33], {{g_bytes + 415, 31}}}, - {&grpc_static_metadata_refcounts[34], {{g_bytes + 446, 36}}}, - {&grpc_static_metadata_refcounts[35], {{g_bytes + 482, 28}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 510, 80}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 590, 7}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 601, 11}}}, - {&grpc_static_metadata_refcounts[40], {{g_bytes + 612, 3}}}, - {&grpc_static_metadata_refcounts[41], {{g_bytes + 615, 4}}}, - {&grpc_static_metadata_refcounts[42], {{g_bytes + 619, 1}}}, - {&grpc_static_metadata_refcounts[43], {{g_bytes + 620, 11}}}, - {&grpc_static_metadata_refcounts[44], {{g_bytes + 631, 4}}}, - {&grpc_static_metadata_refcounts[45], {{g_bytes + 635, 5}}}, - {&grpc_static_metadata_refcounts[46], {{g_bytes + 640, 3}}}, - {&grpc_static_metadata_refcounts[47], {{g_bytes + 643, 3}}}, - {&grpc_static_metadata_refcounts[48], {{g_bytes + 646, 3}}}, - {&grpc_static_metadata_refcounts[49], {{g_bytes + 649, 3}}}, - {&grpc_static_metadata_refcounts[50], {{g_bytes + 652, 3}}}, - {&grpc_static_metadata_refcounts[51], {{g_bytes + 655, 3}}}, - {&grpc_static_metadata_refcounts[52], {{g_bytes + 658, 3}}}, - {&grpc_static_metadata_refcounts[53], {{g_bytes + 661, 14}}}, - {&grpc_static_metadata_refcounts[54], {{g_bytes + 675, 13}}}, - {&grpc_static_metadata_refcounts[55], {{g_bytes + 688, 15}}}, - {&grpc_static_metadata_refcounts[56], {{g_bytes + 703, 13}}}, - {&grpc_static_metadata_refcounts[57], {{g_bytes + 716, 6}}}, - {&grpc_static_metadata_refcounts[58], {{g_bytes + 722, 27}}}, - {&grpc_static_metadata_refcounts[59], {{g_bytes + 749, 3}}}, - {&grpc_static_metadata_refcounts[60], {{g_bytes + 752, 5}}}, - {&grpc_static_metadata_refcounts[61], {{g_bytes + 757, 13}}}, - {&grpc_static_metadata_refcounts[62], {{g_bytes + 770, 13}}}, - {&grpc_static_metadata_refcounts[63], {{g_bytes + 783, 19}}}, - {&grpc_static_metadata_refcounts[64], {{g_bytes + 802, 16}}}, - {&grpc_static_metadata_refcounts[65], {{g_bytes + 818, 14}}}, - {&grpc_static_metadata_refcounts[66], {{g_bytes + 832, 16}}}, - {&grpc_static_metadata_refcounts[67], {{g_bytes + 848, 13}}}, - {&grpc_static_metadata_refcounts[68], {{g_bytes + 861, 6}}}, - {&grpc_static_metadata_refcounts[69], {{g_bytes + 867, 4}}}, - {&grpc_static_metadata_refcounts[70], {{g_bytes + 871, 4}}}, - {&grpc_static_metadata_refcounts[71], {{g_bytes + 875, 6}}}, - {&grpc_static_metadata_refcounts[72], {{g_bytes + 881, 7}}}, - {&grpc_static_metadata_refcounts[73], {{g_bytes + 888, 4}}}, - {&grpc_static_metadata_refcounts[74], {{g_bytes + 892, 8}}}, - {&grpc_static_metadata_refcounts[75], {{g_bytes + 900, 17}}}, - {&grpc_static_metadata_refcounts[76], {{g_bytes + 917, 13}}}, - {&grpc_static_metadata_refcounts[77], {{g_bytes + 930, 8}}}, - {&grpc_static_metadata_refcounts[78], {{g_bytes + 938, 19}}}, - {&grpc_static_metadata_refcounts[79], {{g_bytes + 957, 13}}}, - {&grpc_static_metadata_refcounts[80], {{g_bytes + 970, 4}}}, - {&grpc_static_metadata_refcounts[81], {{g_bytes + 974, 8}}}, - {&grpc_static_metadata_refcounts[82], {{g_bytes + 982, 12}}}, - {&grpc_static_metadata_refcounts[83], {{g_bytes + 994, 18}}}, - {&grpc_static_metadata_refcounts[84], {{g_bytes + 1012, 19}}}, - {&grpc_static_metadata_refcounts[85], {{g_bytes + 1031, 5}}}, - {&grpc_static_metadata_refcounts[86], {{g_bytes + 1036, 7}}}, - {&grpc_static_metadata_refcounts[87], {{g_bytes + 1043, 7}}}, - {&grpc_static_metadata_refcounts[88], {{g_bytes + 1050, 11}}}, - {&grpc_static_metadata_refcounts[89], {{g_bytes + 1061, 6}}}, - {&grpc_static_metadata_refcounts[90], {{g_bytes + 1067, 10}}}, - {&grpc_static_metadata_refcounts[91], {{g_bytes + 1077, 25}}}, - {&grpc_static_metadata_refcounts[92], {{g_bytes + 1102, 17}}}, - {&grpc_static_metadata_refcounts[93], {{g_bytes + 1119, 4}}}, - {&grpc_static_metadata_refcounts[94], {{g_bytes + 1123, 3}}}, - {&grpc_static_metadata_refcounts[95], {{g_bytes + 1126, 16}}}, - {&grpc_static_metadata_refcounts[96], {{g_bytes + 1142, 1}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}, - {&grpc_static_metadata_refcounts[98], {{g_bytes + 1151, 8}}}, - {&grpc_static_metadata_refcounts[99], {{g_bytes + 1159, 16}}}, - {&grpc_static_metadata_refcounts[100], {{g_bytes + 1175, 4}}}, - {&grpc_static_metadata_refcounts[101], {{g_bytes + 1179, 3}}}, - {&grpc_static_metadata_refcounts[102], {{g_bytes + 1182, 11}}}, - {&grpc_static_metadata_refcounts[103], {{g_bytes + 1193, 16}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1209, 13}}}, - {&grpc_static_metadata_refcounts[105], {{g_bytes + 1222, 12}}}, - {&grpc_static_metadata_refcounts[106], {{g_bytes + 1234, 21}}}, + {&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}}, + {&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}}, + {&grpc_static_metadata_refcounts[6], {{12, g_bytes + 38}}}, + {&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[8], {{16, g_bytes + 61}}}, + {&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[11], {{21, g_bytes + 110}}}, + {&grpc_static_metadata_refcounts[12], {{13, g_bytes + 131}}}, + {&grpc_static_metadata_refcounts[13], {{14, g_bytes + 144}}}, + {&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[17], {{30, g_bytes + 201}}}, + {&grpc_static_metadata_refcounts[18], {{37, g_bytes + 231}}}, + {&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}}, + {&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}}, + {&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}}, + {&grpc_static_metadata_refcounts[22], {{26, g_bytes + 290}}}, + {&grpc_static_metadata_refcounts[23], {{22, g_bytes + 316}}}, + {&grpc_static_metadata_refcounts[24], {{12, g_bytes + 338}}}, + {&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}, + {&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}, + {&grpc_static_metadata_refcounts[27], {{1, g_bytes + 352}}}, + {&grpc_static_metadata_refcounts[28], {{1, g_bytes + 353}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, + {&grpc_static_metadata_refcounts[30], {{19, g_bytes + 354}}}, + {&grpc_static_metadata_refcounts[31], {{12, g_bytes + 373}}}, + {&grpc_static_metadata_refcounts[32], {{30, g_bytes + 385}}}, + {&grpc_static_metadata_refcounts[33], {{31, g_bytes + 415}}}, + {&grpc_static_metadata_refcounts[34], {{36, g_bytes + 446}}}, + {&grpc_static_metadata_refcounts[35], {{28, g_bytes + 482}}}, + {&grpc_static_metadata_refcounts[36], {{80, g_bytes + 510}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, + {&grpc_static_metadata_refcounts[39], {{11, g_bytes + 601}}}, + {&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}, + {&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}, + {&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}, + {&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}, + {&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}, + {&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}, + {&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}, + {&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}, + {&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}, + {&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}, + {&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}, + {&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}, + {&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}, + {&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}}, + {&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}, + {&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}}, + {&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}}, + {&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}}, + {&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}}, + {&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}}, + {&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}}, + {&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}}, + {&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}}, + {&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}}, + {&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}}, + {&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}}, + {&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}}, + {&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}}, + {&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}}, + {&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}}, + {&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}}, + {&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}}, + {&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}}, + {&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}}, + {&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}}, + {&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}}, + {&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}}, + {&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}}, + {&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}}, + {&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}}, + {&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}}, + {&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}}, + {&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}}, + {&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}}, + {&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}}, + {&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}}, + {&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}}, + {&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}}, + {&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}}, + {&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}}, + {&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}}, + {&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}}, + {&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}}, + {&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}}, + {&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}}, + {&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}}, + {&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, + {&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}, + {&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}, + {&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}, + {&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}, + {&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}}, + {&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}, + {&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}, + {&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}, }; uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { @@ -404,178 +404,178 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) { } grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { - {{&grpc_static_metadata_refcounts[3], {{g_bytes + 19, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[40], {{g_bytes + 612, 3}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[41], {{g_bytes + 615, 4}}}}, - {{&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[42], {{g_bytes + 619, 1}}}}, - {{&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[43], {{g_bytes + 620, 11}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[44], {{g_bytes + 631, 4}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[45], {{g_bytes + 635, 5}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[46], {{g_bytes + 640, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[47], {{g_bytes + 643, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[48], {{g_bytes + 646, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[49], {{g_bytes + 649, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[50], {{g_bytes + 652, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[51], {{g_bytes + 655, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[52], {{g_bytes + 658, 3}}}}, - {{&grpc_static_metadata_refcounts[53], {{g_bytes + 661, 14}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[54], {{g_bytes + 675, 13}}}}, - {{&grpc_static_metadata_refcounts[55], {{g_bytes + 688, 15}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[56], {{g_bytes + 703, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[57], {{g_bytes + 716, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[58], {{g_bytes + 722, 27}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[59], {{g_bytes + 749, 3}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[60], {{g_bytes + 752, 5}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[61], {{g_bytes + 757, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[62], {{g_bytes + 770, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[63], {{g_bytes + 783, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[64], {{g_bytes + 802, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[65], {{g_bytes + 818, 14}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[66], {{g_bytes + 832, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[67], {{g_bytes + 848, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[68], {{g_bytes + 861, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[69], {{g_bytes + 867, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[70], {{g_bytes + 871, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[71], {{g_bytes + 875, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[72], {{g_bytes + 881, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[73], {{g_bytes + 888, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[20], {{g_bytes + 278, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[74], {{g_bytes + 892, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[75], {{g_bytes + 900, 17}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[76], {{g_bytes + 917, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[77], {{g_bytes + 930, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[78], {{g_bytes + 938, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[79], {{g_bytes + 957, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[80], {{g_bytes + 970, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[81], {{g_bytes + 974, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[82], {{g_bytes + 982, 12}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[83], {{g_bytes + 994, 18}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[84], {{g_bytes + 1012, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[85], {{g_bytes + 1031, 5}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[86], {{g_bytes + 1036, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[87], {{g_bytes + 1043, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[88], {{g_bytes + 1050, 11}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[89], {{g_bytes + 1061, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[90], {{g_bytes + 1067, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[91], {{g_bytes + 1077, 25}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[92], {{g_bytes + 1102, 17}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[19], {{g_bytes + 268, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[93], {{g_bytes + 1119, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[94], {{g_bytes + 1123, 3}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[95], {{g_bytes + 1126, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[96], {{g_bytes + 1142, 1}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[25], {{g_bytes + 350, 1}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[26], {{g_bytes + 351, 1}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 590, 7}}}}, - {{&grpc_static_metadata_refcounts[5], {{g_bytes + 36, 2}}}, - {&grpc_static_metadata_refcounts[98], {{g_bytes + 1151, 8}}}}, - {{&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[99], {{g_bytes + 1159, 16}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[100], {{g_bytes + 1175, 4}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[101], {{g_bytes + 1179, 3}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[21], {{g_bytes + 282, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[102], {{g_bytes + 1182, 11}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 590, 7}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[103], {{g_bytes + 1193, 16}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1209, 13}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[105], {{g_bytes + 1222, 12}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[106], {{g_bytes + 1234, 21}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1209, 13}}}}, + {{&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}}, + {{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}}, + {{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}}, + {{&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}}, + {{&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}}, + {{&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}}, + {&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}}, + {{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}}, }; const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 76, 77, 78, 79, 80, 81, 82}; diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index b18da575382..2107bcaa748 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -619,15 +619,19 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store, sk_X509_NAME_push(*root_names, root_name); root_name = nullptr; } + ERR_clear_error(); if (!X509_STORE_add_cert(cert_store, root)) { - gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); - result = TSI_INTERNAL_ERROR; - break; + unsigned long error = ERR_get_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); + result = TSI_INTERNAL_ERROR; + break; + } } X509_free(root); num_roots++; } - if (num_roots == 0) { gpr_log(GPR_ERROR, "Could not load any root certificate."); result = TSI_INVALID_ARGUMENT; diff --git a/src/cpp/common/alarm.cc b/src/cpp/common/alarm.cc index 6bfe26f04c4..dbec80cde4f 100644 --- a/src/cpp/common/alarm.cc +++ b/src/cpp/common/alarm.cc @@ -40,12 +40,7 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { gpr_ref_init(&refs_, 1); grpc_timer_init_unset(&timer_); } - ~AlarmImpl() { - grpc_core::ExecCtx exec_ctx; - if (cq_ != nullptr) { - GRPC_CQ_INTERNAL_UNREF(cq_, "alarm"); - } - } + ~AlarmImpl() {} bool FinalizeResult(void** tag, bool* status) override { *tag = tag_; Unref(); @@ -63,10 +58,15 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { // queue the op on the completion queue AlarmImpl* alarm = static_cast(arg); alarm->Ref(); + // Preserve the cq and reset the cq_ so that the alarm + // can be reset when the alarm tag is delivered. + grpc_completion_queue* cq = alarm->cq_; + alarm->cq_ = nullptr; grpc_cq_end_op( - alarm->cq_, alarm, error, + cq, alarm, error, [](void* arg, grpc_cq_completion* completion) {}, arg, &alarm->completion_); + GRPC_CQ_INTERNAL_UNREF(cq, "alarm"); }, this, grpc_schedule_on_exec_ctx); grpc_timer_init(&timer_, grpc_timespec_to_millis_round_up(deadline), diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 0dc03b68768..64210a2f8d1 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -139,6 +139,7 @@ ServerBuilder& ServerBuilder::SetCompressionAlgorithmSupportStatus( ServerBuilder& ServerBuilder::SetDefaultCompressionLevel( grpc_compression_level level) { + maybe_default_compression_level_.is_set = true; maybe_default_compression_level_.level = level; return *this; } diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 1e642681467..05f78dbe6fe 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -350,10 +350,10 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { class Server::CallbackRequest final : public internal::CompletionQueueTag { public: - CallbackRequest(Server* server, Server::MethodReqList* list, + CallbackRequest(Server* server, size_t method_idx, internal::RpcServiceMethod* method, void* method_tag) : server_(server), - req_list_(list), + method_index_(method_idx), method_(method), method_tag_(method_tag), has_request_payload_( @@ -428,46 +428,32 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); GPR_ASSERT(ignored == req_); - bool spawn_new = false; - { - std::unique_lock l(req_->req_list_->reqs_mu); - req_->req_list_->reqs_list.erase(req_->req_list_iterator_); - req_->req_list_->reqs_list_sz--; - if (!ok) { - // The call has been shutdown. - // Delete its contents to free up the request. - // First release the lock in case the deletion of the request - // completes the full server shutdown and allows the destructor - // of the req_list to proceed. - l.unlock(); - delete req_; - return; - } - - // If this was the last request in the list or it is below the soft - // minimum and there are spare requests available, set up a new one, but - // do it outside the lock since the Request could otherwise deadlock - if (req_->req_list_->reqs_list_sz == 0 || - (req_->req_list_->reqs_list_sz < - SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && - req_->server_->callback_reqs_outstanding_ < - SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { - spawn_new = true; - } + int count = + static_cast(gpr_atm_no_barrier_fetch_add( + &req_->server_ + ->callback_unmatched_reqs_count_[req_->method_index_], + -1)) - + 1; + if (!ok) { + // The call has been shutdown. + // Delete its contents to free up the request. + delete req_; + return; } - if (spawn_new) { - auto* new_req = new CallbackRequest(req_->server_, req_->req_list_, + + // If this was the last request in the list or it is below the soft + // minimum and there are spare requests available, set up a new one. + if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && + req_->server_->callback_reqs_outstanding_ < + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + auto* new_req = new CallbackRequest(req_->server_, req_->method_index_, req_->method_, req_->method_tag_); if (!new_req->Request()) { - // The server must have just decided to shutdown. Erase - // from the list under lock but release the lock before - // deleting the new_req (in case that request was what - // would allow the destruction of the req_list) - { - std::lock_guard l(new_req->req_list_->reqs_mu); - new_req->req_list_->reqs_list.erase(new_req->req_list_iterator_); - new_req->req_list_->reqs_list_sz--; - } + // The server must have just decided to shutdown. + gpr_atm_no_barrier_fetch_add( + &new_req->server_ + ->callback_unmatched_reqs_count_[new_req->method_index_], + -1); delete new_req; } } @@ -557,20 +543,17 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { } void Setup() { + gpr_atm_no_barrier_fetch_add( + &server_->callback_unmatched_reqs_count_[method_index_], 1); grpc_metadata_array_init(&request_metadata_); ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); request_payload_ = nullptr; request_ = nullptr; request_status_ = Status(); - std::lock_guard l(req_list_->reqs_mu); - req_list_->reqs_list.push_front(this); - req_list_->reqs_list_sz++; - req_list_iterator_ = req_list_->reqs_list.begin(); } Server* const server_; - Server::MethodReqList* req_list_; - Server::MethodReqList::iterator req_list_iterator_; + size_t method_index_; internal::RpcServiceMethod* const method_; void* const method_tag_; const bool has_request_payload_; @@ -791,12 +774,12 @@ Server::~Server() { } grpc_server_destroy(server_); - for (auto* method_list : callback_reqs_) { - // The entries of the method_list should have already been emptied - // during Shutdown as each request is failed by Shutdown. Check that - // this actually happened. - GPR_ASSERT(method_list->reqs_list.empty()); - delete method_list; + for (auto& per_method_count : callback_unmatched_reqs_count_) { + // There should be no more unmatched callbacks for any method + // as each request is failed by Shutdown. Check that this actually + // happened + GPR_ASSERT(static_cast(gpr_atm_no_barrier_load(&per_method_count)) == + 0); } } @@ -852,6 +835,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } const char* method_name = nullptr; + for (auto it = service->methods_.begin(); it != service->methods_.end(); ++it) { if (it->get() == nullptr) { // Handled by generic service if any. @@ -877,15 +861,15 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } } else { // a callback method. Register at least some callback requests - callback_reqs_.push_back(new Server::MethodReqList); - auto* method_req_list = callback_reqs_.back(); + callback_unmatched_reqs_count_.push_back(0); + auto method_index = callback_unmatched_reqs_count_.size() - 1; // TODO(vjpai): Register these dynamically based on need for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - new CallbackRequest(this, method_req_list, method, - method_registration_tag); + callback_reqs_to_start_.push_back(new CallbackRequest( + this, method_index, method, method_registration_tag)); } - // Enqueue it so that it will be Request'ed later once - // all request matchers are created at core server startup + // Enqueue it so that it will be Request'ed later after all request + // matchers are created at core server startup } method_name = method->name(); @@ -974,11 +958,10 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { (*it)->Start(); } - for (auto* cbmethods : callback_reqs_) { - for (auto* cbreq : cbmethods->reqs_list) { - GPR_ASSERT(cbreq->Request()); - } + for (auto* cbreq : callback_reqs_to_start_) { + GPR_ASSERT(cbreq->Request()); } + callback_reqs_to_start_.clear(); if (default_health_check_service_impl != nullptr) { default_health_check_service_impl->StartServingThread(); diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs similarity index 74% rename from src/csharp/Grpc.Core/ServerServiceDefinition.cs rename to src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs index b040ab379c8..8c76f0bcc97 100644 --- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs +++ b/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs @@ -18,33 +18,31 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Grpc.Core.Interceptors; -using Grpc.Core.Internal; -using Grpc.Core.Utils; namespace Grpc.Core { /// - /// Mapping of method names to server call handlers. + /// Stores mapping of methods to server call handlers. /// Normally, the ServerServiceDefinition objects will be created by the BindService factory method /// that is part of the autogenerated code for a protocol buffers service definition. /// public class ServerServiceDefinition { - readonly ReadOnlyDictionary callHandlers; + readonly IReadOnlyList> addMethodActions; - internal ServerServiceDefinition(Dictionary callHandlers) + internal ServerServiceDefinition(List> addMethodActions) { - this.callHandlers = new ReadOnlyDictionary(callHandlers); + this.addMethodActions = addMethodActions.AsReadOnly(); } - internal IDictionary CallHandlers + /// + /// Forwards all the previously stored AddMethod calls to the service binder. + /// + internal void BindService(ServiceBinderBase serviceBinder) { - get + foreach (var addMethodAction in addMethodActions) { - return this.callHandlers; + addMethodAction(serviceBinder); } } @@ -62,7 +60,10 @@ namespace Grpc.Core /// public class Builder { - readonly Dictionary callHandlers = new Dictionary(); + // to maintain legacy behavior, we need to detect duplicate keys and throw the same exception as before + readonly Dictionary duplicateDetector = new Dictionary(); + // for each AddMethod call, we store an action that will later register the method and handler with ServiceBinderBase + readonly List> addMethodActions = new List>(); /// /// Creates a new instance of builder. @@ -85,7 +86,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.UnaryCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -103,7 +105,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.ClientStreamingCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -121,7 +124,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.ServerStreamingCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -139,7 +143,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.DuplexStreamingCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -149,7 +154,7 @@ namespace Grpc.Core /// The ServerServiceDefinition object. public ServerServiceDefinition Build() { - return new ServerServiceDefinition(callHandlers); + return new ServerServiceDefinition(addMethodActions); } } } diff --git a/src/csharp/Grpc.Core/ServiceBinderBase.cs b/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs similarity index 97% rename from src/csharp/Grpc.Core/ServiceBinderBase.cs rename to src/csharp/Grpc.Core.Api/ServiceBinderBase.cs index d4909f4a269..074bfae1ea0 100644 --- a/src/csharp/Grpc.Core/ServiceBinderBase.cs +++ b/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs @@ -20,8 +20,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using Grpc.Core.Interceptors; -using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core @@ -30,7 +28,6 @@ namespace Grpc.Core /// Allows binding server-side method implementations in alternative serving stacks. /// Instances of this class are usually populated by the BindService method /// that is part of the autogenerated code for a protocol buffers service definition. - /// /// public class ServiceBinderBase { diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index 8e104fd410d..e17696a626f 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -25,7 +25,6 @@ using Grpc.Core.Utils; // https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime // TODO(jtattermusch): move types needed for implementing a client -// TODO(jtattermusch): ServerServiceDefinition depends on IServerCallHandler (which depends on other stuff) [assembly:TypeForwardedToAttribute(typeof(ILogger))] [assembly:TypeForwardedToAttribute(typeof(LogLevel))] @@ -50,6 +49,8 @@ using Grpc.Core.Utils; [assembly:TypeForwardedToAttribute(typeof(ClientStreamingServerMethod<,>))] [assembly:TypeForwardedToAttribute(typeof(ServerStreamingServerMethod<,>))] [assembly:TypeForwardedToAttribute(typeof(DuplexStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ServerServiceDefinition))] +[assembly:TypeForwardedToAttribute(typeof(ServiceBinderBase))] [assembly:TypeForwardedToAttribute(typeof(Status))] [assembly:TypeForwardedToAttribute(typeof(StatusCode))] [assembly:TypeForwardedToAttribute(typeof(WriteOptions))] diff --git a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs index 56ead8a6a15..321cf080faa 100644 --- a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs +++ b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs @@ -44,7 +44,10 @@ namespace Grpc.Core.Interceptors { GrpcPreconditions.CheckNotNull(serverServiceDefinition, nameof(serverServiceDefinition)); GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); - return new ServerServiceDefinition(serverServiceDefinition.CallHandlers.ToDictionary(x => x.Key, x => x.Value.Intercept(interceptor))); + + var binder = new InterceptingServiceBinder(interceptor); + serverServiceDefinition.BindService(binder); + return binder.GetInterceptedServerServiceDefinition(); } /// @@ -75,5 +78,52 @@ namespace Grpc.Core.Interceptors return serverServiceDefinition; } + + /// + /// Helper for creating ServerServiceDefinition with intercepted handlers. + /// + private class InterceptingServiceBinder : ServiceBinderBase + { + readonly ServerServiceDefinition.Builder builder = ServerServiceDefinition.CreateBuilder(); + readonly Interceptor interceptor; + + public InterceptingServiceBinder(Interceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + } + + internal ServerServiceDefinition GetInterceptedServerServiceDefinition() + { + return builder.Build(); + } + + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + builder.AddMethod(method, (request, context) => interceptor.UnaryServerHandler(request, context, handler)); + } + + public override void AddMethod( + Method method, + ClientStreamingServerMethod handler) + { + builder.AddMethod(method, (requestStream, context) => interceptor.ClientStreamingServerHandler(requestStream, context, handler)); + } + + public override void AddMethod( + Method method, + ServerStreamingServerMethod handler) + { + builder.AddMethod(method, (request, responseStream, context) => interceptor.ServerStreamingServerHandler(request, responseStream, context, handler)); + } + + public override void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + { + builder.AddMethod(method, (requestStream, responseStream, context) => interceptor.DuplexStreamingServerHandler(requestStream, responseStream, context, handler)); + } + } } } diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs index c3859f1de27..0c9297413c3 100644 --- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs @@ -31,7 +31,6 @@ namespace Grpc.Core.Internal internal interface IServerCallHandler { Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq); - IServerCallHandler Intercept(Interceptor interceptor); } internal class UnaryServerCallHandler : IServerCallHandler @@ -91,11 +90,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new UnaryServerCallHandler(method, (request, context) => interceptor.UnaryServerHandler(request, context, handler)); - } } internal class ServerStreamingServerCallHandler : IServerCallHandler @@ -154,11 +148,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new ServerStreamingServerCallHandler(method, (request, responseStream, context) => interceptor.ServerStreamingServerHandler(request, responseStream, context, handler)); - } } internal class ClientStreamingServerCallHandler : IServerCallHandler @@ -217,11 +206,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new ClientStreamingServerCallHandler(method, (requestStream, context) => interceptor.ClientStreamingServerHandler(requestStream, context, handler)); - } } internal class DuplexStreamingServerCallHandler : IServerCallHandler @@ -277,11 +261,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new DuplexStreamingServerCallHandler(method, (requestStream, responseStream, context) => interceptor.DuplexStreamingServerHandler(requestStream, responseStream, context, handler)); - } } internal class UnimplementedMethodCallHandler : IServerCallHandler @@ -310,11 +289,6 @@ namespace Grpc.Core.Internal { return callHandlerImpl.HandleCall(newRpc, cq); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return this; // Do not intercept unimplemented methods. - } } internal static class HandlerUtils diff --git a/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs new file mode 100644 index 00000000000..cc4654c9acf --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs @@ -0,0 +1,78 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Grpc.Core.Internal; + +namespace Grpc.Core.Internal +{ + internal static class ServerServiceDefinitionExtensions + { + /// + /// Maps methods from ServerServiceDefinition to server call handlers. + /// + internal static ReadOnlyDictionary GetCallHandlers(this ServerServiceDefinition serviceDefinition) + { + var binder = new DefaultServiceBinder(); + serviceDefinition.BindService(binder); + return binder.GetCallHandlers(); + } + + /// + /// Helper for converting ServerServiceDefinition to server call handlers. + /// + private class DefaultServiceBinder : ServiceBinderBase + { + readonly Dictionary callHandlers = new Dictionary(); + + internal ReadOnlyDictionary GetCallHandlers() + { + return new ReadOnlyDictionary(this.callHandlers); + } + + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.UnaryCall(method, handler)); + } + + public override void AddMethod( + Method method, + ClientStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.ClientStreamingCall(method, handler)); + } + + public override void AddMethod( + Method method, + ServerStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.ServerStreamingCall(method, handler)); + } + + public override void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.DuplexStreamingCall(method, handler)); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs index 64bb407c57f..26d182ae53b 100644 --- a/src/csharp/Grpc.Core/Server.cs +++ b/src/csharp/Grpc.Core/Server.cs @@ -257,7 +257,7 @@ namespace Grpc.Core lock (myLock) { GrpcPreconditions.CheckState(!startRequested); - foreach (var entry in serviceDefinition.CallHandlers) + foreach (var entry in serviceDefinition.GetCallHandlers()) { callHandlers.Add(entry.Key, entry.Value); } diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index b44840272c9..6caaece82c4 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -100,7 +100,7 @@ class _RPCState(object): self.statused = False self.rpc_errors = [] self.callbacks = [] - self.abortion = None + self.aborted = False def _raise_rpc_error(state): @@ -287,8 +287,8 @@ class _Context(grpc.ServicerContext): with self._state.condition: self._state.code = code self._state.details = _common.encode(details) - self._state.abortion = Exception() - raise self._state.abortion + self._state.aborted = True + raise Exception() def abort_with_status(self, status): self._state.trailing_metadata = status.trailing_metadata @@ -392,7 +392,7 @@ def _call_behavior(rpc_event, state, behavior, argument, request_deserializer): return behavior(argument, context), True except Exception as exception: # pylint: disable=broad-except with state.condition: - if exception is state.abortion: + if state.aborted: _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, b'RPC Aborted') elif exception not in state.rpc_errors: @@ -410,7 +410,7 @@ def _take_response_from_response_iterator(rpc_event, state, response_iterator): return None, True except Exception as exception: # pylint: disable=broad-except with state.condition: - if exception is state.abortion: + if state.aborted: _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, b'RPC Aborted') elif exception not in state.rpc_errors: diff --git a/src/python/grpcio_tests/tests/unit/_abort_test.py b/src/python/grpcio_tests/tests/unit/_abort_test.py index 6438f6897a0..64952c899e4 100644 --- a/src/python/grpcio_tests/tests/unit/_abort_test.py +++ b/src/python/grpcio_tests/tests/unit/_abort_test.py @@ -15,7 +15,9 @@ import unittest import collections +import gc import logging +import weakref import grpc @@ -39,7 +41,15 @@ class _Status( pass +class _Object(object): + pass + + +do_not_leak_me = _Object() + + def abort_unary_unary(request, servicer_context): + this_should_not_be_leaked = do_not_leak_me servicer_context.abort( grpc.StatusCode.INTERNAL, _ABORT_DETAILS, @@ -101,6 +111,24 @@ class AbortTest(unittest.TestCase): self.assertEqual(rpc_error.code(), grpc.StatusCode.INTERNAL) self.assertEqual(rpc_error.details(), _ABORT_DETAILS) + # This test ensures that abort() does not store the raised exception, which + # on Python 3 (via the `__traceback__` attribute) holds a reference to + # all local vars. Storing the raised exception can prevent GC and stop the + # grpc_call from being unref'ed, even after server shutdown. + def test_abort_does_not_leak_local_vars(self): + global do_not_leak_me # pylint: disable=global-statement + weak_ref = weakref.ref(do_not_leak_me) + + # Servicer will abort() after creating a local ref to do_not_leak_me. + with self.assertRaises(grpc.RpcError): + self._channel.unary_unary(_ABORT)(_REQUEST) + + # Server may still have a stack frame reference to the exception even + # after client sees error, so ensure server has shutdown. + self._server.stop(None) + do_not_leak_me = None + self.assertIsNone(weak_ref()) + def test_abort_with_status(self): with self.assertRaises(grpc.RpcError) as exception_context: self._channel.unary_unary(_ABORT_WITH_STATUS)(_REQUEST) diff --git a/templates/tools/dockerfile/bazel.include b/templates/tools/dockerfile/bazel.include index c7714f56630..62d68607453 100644 --- a/templates/tools/dockerfile/bazel.include +++ b/templates/tools/dockerfile/bazel.include @@ -2,5 +2,6 @@ # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O /usr/local/bin/bazel -RUN chmod 755 /usr/local/bin/bazel +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} + bash ./bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} + rm bazel-0.20.0-installer-linux-x86_64.sh diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template index a4f9183beac..2e4bdf537b7 100644 --- a/templates/tools/dockerfile/test/sanity/Dockerfile.template +++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template @@ -32,6 +32,7 @@ RUN python3 -m pip install simplejson mako virtualenv lxml <%include file="../../clang5.include"/> + <%include file="../../bazel.include"/> # Define the default command. CMD ["bash"] diff --git a/test/core/bad_connection/BUILD b/test/core/bad_connection/BUILD new file mode 100644 index 00000000000..8ada933e796 --- /dev/null +++ b/test/core/bad_connection/BUILD @@ -0,0 +1,32 @@ +# Copyright 2016 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package") + +licenses(["notice"]) # Apache v2 + +grpc_package(name = "test/core/bad_connection") + +grpc_cc_binary( + name = "close_fd_test", + srcs = [ + "close_fd_test.cc", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/bad_connection/close_fd_test.cc b/test/core/bad_connection/close_fd_test.cc new file mode 100644 index 00000000000..317526a563a --- /dev/null +++ b/test/core/bad_connection/close_fd_test.cc @@ -0,0 +1,764 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * close_fd_test tests the behavior of grpc core when the transport gets + * disconnected. + * The test creates an http2 transport over a socket pair and closes the + * client or server file descriptor to simulate connection breakage while + * an RPC call is in progress. + * + */ +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "test/core/util/test_config.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" + +static void* tag(intptr_t t) { return (void*)t; } + +typedef struct test_ctx test_ctx; + +struct test_ctx { + /* completion queue for call notifications on the server */ + grpc_completion_queue* cq; + /* completion queue registered to server for shutdown events */ + grpc_completion_queue* shutdown_cq; + /* client's completion queue */ + grpc_completion_queue* client_cq; + /* completion queue bound to call on the server */ + grpc_completion_queue* bound_cq; + /* Server responds to client calls */ + grpc_server* server; + /* Client calls are sent over the channel */ + grpc_channel* client; + /* encapsulates client, server endpoints */ + grpc_endpoint_pair* ep; +}; + +static test_ctx g_ctx; + +/* chttp2 transport that is immediately available (used for testing + connected_channel without a client_channel */ + +static void server_setup_transport(grpc_transport* transport) { + grpc_core::ExecCtx exec_ctx; + grpc_endpoint_add_to_pollset(g_ctx.ep->server, grpc_cq_pollset(g_ctx.cq)); + grpc_server_setup_transport(g_ctx.server, transport, nullptr, + grpc_server_get_channel_args(g_ctx.server), + nullptr); +} + +static void client_setup_transport(grpc_transport* transport) { + grpc_core::ExecCtx exec_ctx; + grpc_endpoint_add_to_pollset(g_ctx.ep->client, + grpc_cq_pollset(g_ctx.client_cq)); + grpc_arg authority_arg = grpc_channel_arg_string_create( + const_cast(GRPC_ARG_DEFAULT_AUTHORITY), + const_cast("test-authority")); + grpc_channel_args* args = + grpc_channel_args_copy_and_add(nullptr, &authority_arg, 1); + /* TODO (pjaikumar): use GRPC_CLIENT_CHANNEL instead of + * GRPC_CLIENT_DIRECT_CHANNEL */ + g_ctx.client = grpc_channel_create("socketpair-target", args, + GRPC_CLIENT_DIRECT_CHANNEL, transport); + grpc_channel_args_destroy(args); +} + +static void init_client() { + grpc_core::ExecCtx exec_ctx; + grpc_transport* transport; + transport = grpc_create_chttp2_transport(nullptr, g_ctx.ep->client, true); + client_setup_transport(transport); + GPR_ASSERT(g_ctx.client); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); +} + +static void init_server() { + grpc_core::ExecCtx exec_ctx; + grpc_transport* transport; + GPR_ASSERT(!g_ctx.server); + g_ctx.server = grpc_server_create(nullptr, nullptr); + grpc_server_register_completion_queue(g_ctx.server, g_ctx.cq, nullptr); + grpc_server_start(g_ctx.server); + transport = grpc_create_chttp2_transport(nullptr, g_ctx.ep->server, false); + server_setup_transport(transport); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); +} + +static void test_init() { + grpc_endpoint_pair* sfd = + static_cast(gpr_malloc(sizeof(grpc_endpoint_pair))); + memset(&g_ctx, 0, sizeof(g_ctx)); + g_ctx.ep = sfd; + g_ctx.cq = grpc_completion_queue_create_for_next(nullptr); + g_ctx.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr); + g_ctx.bound_cq = grpc_completion_queue_create_for_next(nullptr); + g_ctx.client_cq = grpc_completion_queue_create_for_next(nullptr); + + /* Create endpoints */ + *sfd = grpc_iomgr_create_endpoint_pair("fixture", nullptr); + /* Create client, server and setup transport over endpoint pair */ + init_server(); + init_client(); +} + +static void drain_cq(grpc_completion_queue* cq) { + grpc_event event; + do { + event = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(1), + nullptr); + } while (event.type != GRPC_QUEUE_SHUTDOWN); +} + +static void drain_and_destroy_cq(grpc_completion_queue* cq) { + grpc_completion_queue_shutdown(cq); + drain_cq(cq); + grpc_completion_queue_destroy(cq); +} + +static void shutdown_server() { + if (!g_ctx.server) return; + grpc_server_shutdown_and_notify(g_ctx.server, g_ctx.shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(g_ctx.shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(1), + nullptr) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(g_ctx.server); + g_ctx.server = nullptr; +} + +static void shutdown_client() { + if (!g_ctx.client) return; + grpc_channel_destroy(g_ctx.client); + g_ctx.client = nullptr; +} + +static void end_test() { + shutdown_server(); + shutdown_client(); + + drain_and_destroy_cq(g_ctx.cq); + drain_and_destroy_cq(g_ctx.client_cq); + drain_and_destroy_cq(g_ctx.bound_cq); + grpc_completion_queue_destroy(g_ctx.shutdown_cq); + gpr_free(g_ctx.ep); +} + +typedef enum fd_type { CLIENT_FD, SERVER_FD } fd_type; + +static const char* fd_type_str(fd_type fdtype) { + if (fdtype == CLIENT_FD) { + return "client"; + } else if (fdtype == SERVER_FD) { + return "server"; + } else { + gpr_log(GPR_ERROR, "Unexpected fd_type %d", fdtype); + abort(); + } +} + +static void _test_close_before_server_recv(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_call* server_call; + grpc_event event; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_log(GPR_INFO, "Running test: test_close_%s_before_server_recv", + fd_type_str(fdtype)); + test_init(); + + 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* request_payload_recv = nullptr; + grpc_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status = GRPC_STATUS__DO_NOT_USE; + grpc_call_error error; + grpc_slice details; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + 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->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(call, ops, static_cast(op - ops), + tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = grpc_server_request_call(g_ctx.server, &server_call, &call_details, + &request_metadata_recv, g_ctx.bound_cq, + g_ctx.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(101)); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + /* Connection is closed before the server receives the client's message. */ + close(fd); + + error = grpc_call_start_batch(server_call, ops, static_cast(op - ops), + tag(102), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + event = grpc_completion_queue_next( + g_ctx.bound_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + + /* Batch operation completes on the server side. + * event.success will be true if the op completes successfully. + * event.success will be false if the op completes with an error. This can + * happen due to a race with closing the fd resulting in pending writes + * failing due to stream closure. + * */ + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.tag == tag(102)); + + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + /* When the client fd is closed, the server gets EPIPE. + * When server fd is closed, server gets EBADF. + * In both cases server sends GRPC_STATUS_UNAVALABLE to the client. However, + * the client may not receive this grpc_status as it's socket is being closed. + * If the client didn't get grpc_status from the server it will time out + * waiting on the completion queue. So there 2 2 possibilities: + * 1. client times out waiting for server's response + * 2. client receives GRPC_STATUS_UNAVAILABLE from server + */ + if (event.type == GRPC_QUEUE_TIMEOUT) { + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + /* status is not initialized */ + GPR_ASSERT(status == GRPC_STATUS__DO_NOT_USE); + } else { + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(1)); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + } + + 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_unref(call); + grpc_call_unref(server_call); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(); +} + +static void test_close_before_server_recv() { + /* Close client side of the connection before server receives message from + * client */ + _test_close_before_server_recv(CLIENT_FD); + /* Close server side of the connection before server receives message from + * client */ + _test_close_before_server_recv(SERVER_FD); +} + +static void _test_close_before_server_send(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_call* server_call; + grpc_event event; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_log(GPR_INFO, "Running test: test_close_%s_before_server_send", + fd_type_str(fdtype)); + test_init(); + + 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* request_payload_recv = nullptr; + grpc_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status = GRPC_STATUS__DO_NOT_USE; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + 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->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(call, ops, static_cast(op - ops), + tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = grpc_server_request_call(g_ctx.server, &server_call, &call_details, + &request_metadata_recv, g_ctx.bound_cq, + g_ctx.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(101)); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(server_call, ops, static_cast(op - ops), + tag(102), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + event = grpc_completion_queue_next( + g_ctx.bound_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(102)); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = nullptr; + op++; + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + + /* Connection is closed before the server sends message and status to the + * client. */ + close(fd); + error = grpc_call_start_batch(server_call, ops, static_cast(op - ops), + tag(103), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* Batch operation succeeds on the server side */ + event = grpc_completion_queue_next( + g_ctx.bound_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(103)); + + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + /* In both cases server sends GRPC_STATUS_UNAVALABLE to the client. However, + * the client may not receive this grpc_status as it's socket is being closed. + * If the client didn't get grpc_status from the server it will time out + * waiting on the completion queue + */ + if (event.type == GRPC_OP_COMPLETE) { + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(1)); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + } else { + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + /* status is not initialized */ + GPR_ASSERT(status == GRPC_STATUS__DO_NOT_USE); + } + GPR_ASSERT(was_cancelled == 0); + + 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_unref(call); + grpc_call_unref(server_call); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(); +} + +static void test_close_before_server_send() { + /* Close client side of the connection before server sends message to client + * */ + _test_close_before_server_send(CLIENT_FD); + /* Close server side of the connection before server sends message to client + * */ + _test_close_before_server_send(SERVER_FD); +} + +static void _test_close_before_client_send(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_event event; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_log(GPR_INFO, "Running test: test_close_%s_before_client_send", + fd_type_str(fdtype)); + test_init(); + + 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* request_payload_recv = nullptr; + grpc_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + 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->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = nullptr; + op++; + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + /* Connection is closed before the client sends a batch to the server */ + close(fd); + + error = grpc_call_start_batch(call, ops, static_cast(op - ops), + tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* Status unavailable is returned to the client when client or server fd is + * closed */ + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.tag == tag(1)); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + + /* No event is received on the server */ + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.tag == nullptr); + + 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_unref(call); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(); +} +static void test_close_before_client_send() { + /* Close client side of the connection before client sends message to server + * */ + _test_close_before_client_send(CLIENT_FD); + /* Close server side of the connection before client sends message to server + * */ + _test_close_before_client_send(SERVER_FD); +} + +static void _test_close_before_call_create(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_event event; + test_init(); + + gpr_timespec deadline = grpc_timeout_milliseconds_to_deadline(100); + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + /* Connection is closed before the client creates a call */ + close(fd); + + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + /* Client and server time out waiting on their completion queues and nothing + * is sent or received */ + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + + grpc_call_unref(call); + end_test(); +} + +static void test_close_before_call_create() { + /* Close client side of the connection before client creates a call */ + _test_close_before_call_create(CLIENT_FD); + /* Close server side of the connection before client creates a call */ + _test_close_before_call_create(SERVER_FD); +} + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + /* Init grpc */ + grpc_init(); + int iterations = 10; + + for (int i = 0; i < iterations; ++i) { + test_close_before_call_create(); + test_close_before_client_send(); + test_close_before_server_recv(); + test_close_before_server_send(); + } + + grpc_shutdown(); + + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char** argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index ed3d629dc99..31841f9f967 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -112,7 +112,7 @@ TEST_F(ChannelzRegistryTest, NullIfNotPresentTest) { } TEST_F(ChannelzRegistryTest, TestCompaction) { - const int kLoopIterations = 100; + const int kLoopIterations = 300; // These channels that will stay in the registry for the duration of the test. std::vector> even_channels; even_channels.reserve(kLoopIterations); diff --git a/test/core/iomgr/timer_heap_test.cc b/test/core/iomgr/timer_heap_test.cc index 872cf17486f..b574e0a680e 100644 --- a/test/core/iomgr/timer_heap_test.cc +++ b/test/core/iomgr/timer_heap_test.cc @@ -164,13 +164,13 @@ static void test2(void) { size_t num_inserted = 0; grpc_timer_heap_init(&pq); - memset(elems, 0, elems_size); + memset(elems, 0, elems_size * sizeof(elems[0])); for (size_t round = 0; round < 10000; round++) { int r = rand() % 1000; if (r <= 550) { /* 55% of the time we try to add something */ - elem_struct* el = search_elems(elems, GPR_ARRAY_SIZE(elems), false); + elem_struct* el = search_elems(elems, elems_size, false); if (el != nullptr) { el->elem.deadline = random_deadline(); grpc_timer_heap_add(&pq, &el->elem); @@ -180,7 +180,7 @@ static void test2(void) { } } else if (r <= 650) { /* 10% of the time we try to remove something */ - elem_struct* el = search_elems(elems, GPR_ARRAY_SIZE(elems), true); + elem_struct* el = search_elems(elems, elems_size, true); if (el != nullptr) { grpc_timer_heap_remove(&pq, &el->elem); el->inserted = false; diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index b6555353359..11cfc8cc905 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -534,7 +534,7 @@ static void test_channel_oauth2_google_iam_composite_creds(void) { static void validate_compute_engine_http_request( const grpc_httpcli_request* request) { GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0); GPR_ASSERT( strcmp(request->http.path, "/computeMetadata/v1/instance/service-accounts/default/token") == @@ -930,7 +930,7 @@ static int default_creds_metadata_server_detection_httpcli_get_success_override( response->hdr_count = 1; response->hdrs = headers; GPR_ASSERT(strcmp(request->http.path, "/") == 0); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0); GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); return 1; } @@ -1020,7 +1020,7 @@ static int default_creds_gce_detection_httpcli_get_failure_override( grpc_closure* on_done, grpc_httpcli_response* response) { /* No magic header. */ GPR_ASSERT(strcmp(request->http.path, "/") == 0); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0); *response = http_response(200, ""); GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); return 1; diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index fc6c6ba3208..033618a2d42 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -776,10 +776,24 @@ void ssl_tsi_test_handshaker_factory_internals() { test_tsi_ssl_client_handshaker_factory_bad_params(); } +void ssl_tsi_test_duplicate_root_certificates() { + char* root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem"); + char* dup_root_cert = static_cast( + gpr_zalloc(sizeof(char) * (strlen(root_cert) * 2 + 1))); + memcpy(dup_root_cert, root_cert, strlen(root_cert)); + memcpy(dup_root_cert + strlen(root_cert), root_cert, strlen(root_cert)); + tsi_ssl_root_certs_store* root_store = + tsi_ssl_root_certs_store_create(dup_root_cert); + GPR_ASSERT(root_store != nullptr); + // Free memory. + tsi_ssl_root_certs_store_destroy(root_store); + gpr_free(root_cert); + gpr_free(dup_root_cert); +} + int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); grpc_init(); - ssl_tsi_test_do_handshake_tiny_handshake_buffer(); ssl_tsi_test_do_handshake_small_handshake_buffer(); ssl_tsi_test_do_handshake(); @@ -801,6 +815,7 @@ int main(int argc, char** argv) { ssl_tsi_test_do_round_trip_for_all_configs(); ssl_tsi_test_do_round_trip_odd_buffer_size(); ssl_tsi_test_handshaker_factory_internals(); + ssl_tsi_test_duplicate_root_certificates(); grpc_shutdown(); return 0; } diff --git a/test/core/util/ubsan_suppressions.txt b/test/core/util/ubsan_suppressions.txt index 8ed7d4d7fb6..8e17d37ec7e 100644 --- a/test/core/util/ubsan_suppressions.txt +++ b/test/core/util/ubsan_suppressions.txt @@ -1,11 +1,4 @@ -# boringssl stuff -nonnull-attribute:bn_wexpand -nonnull-attribute:CBB_add_bytes -nonnull-attribute:rsa_blinding_get -nonnull-attribute:ssl_copy_key_material -alignment:CRYPTO_cbc128_encrypt -alignment:CRYPTO_gcm128_encrypt -alignment:poly1305_block_copy +# Protobuf stuff nonnull-attribute:google::protobuf::* alignment:google::protobuf::* nonnull-attribute:_tr_stored_block diff --git a/test/cpp/common/alarm_test.cc b/test/cpp/common/alarm_test.cc index 802cdc209a0..4d410a5d460 100644 --- a/test/cpp/common/alarm_test.cc +++ b/test/cpp/common/alarm_test.cc @@ -47,6 +47,44 @@ TEST(AlarmTest, RegularExpiry) { EXPECT_EQ(junk, output_tag); } +TEST(AlarmTest, RegularExpiryMultiSet) { + CompletionQueue cq; + void* junk = reinterpret_cast(1618033); + Alarm alarm; + + for (int i = 0; i < 3; i++) { + alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk); + + void* output_tag; + bool ok; + const CompletionQueue::NextStatus status = + cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10)); + + EXPECT_EQ(status, CompletionQueue::GOT_EVENT); + EXPECT_TRUE(ok); + EXPECT_EQ(junk, output_tag); + } +} + +TEST(AlarmTest, RegularExpiryMultiSetMultiCQ) { + void* junk = reinterpret_cast(1618033); + Alarm alarm; + + for (int i = 0; i < 3; i++) { + CompletionQueue cq; + alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk); + + void* output_tag; + bool ok; + const CompletionQueue::NextStatus status = + cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10)); + + EXPECT_EQ(status, CompletionQueue::GOT_EVENT); + EXPECT_TRUE(ok); + EXPECT_EQ(junk, output_tag); + } +} + struct Completion { bool completed = false; std::mutex mu; diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 4c28eee4d15..cbf09354a03 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -80,6 +80,27 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "time_change_test", + srcs = ["time_change_test.cc"], + data = [ + ":client_crash_test_server", + ], + external_deps = [ + "gtest", + ], + deps = [ + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + grpc_cc_test( name = "client_crash_test", srcs = ["client_crash_test.cc"], @@ -110,6 +131,7 @@ grpc_cc_binary( "gtest", ], deps = [ + ":test_service_impl", "//:gpr", "//:grpc", "//:grpc++", @@ -219,10 +241,10 @@ grpc_cc_test( grpc_cc_test( name = "end2end_test", + size = "large", # with poll-cv this takes long, see #17493 deps = [ ":end2end_test_lib", ], - size = "large", # with poll-cv this takes long, see #17493 ) grpc_cc_test( diff --git a/test/cpp/end2end/time_change_test.cc b/test/cpp/end2end/time_change_test.cc new file mode 100644 index 00000000000..9fbd01299d0 --- /dev/null +++ b/test/cpp/end2end/time_change_test.cc @@ -0,0 +1,422 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/timer.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/subprocess.h" + +#include +#include +#include +#include + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +static std::string g_root; + +static gpr_mu g_mu; +extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); +gpr_timespec (*gpr_now_impl_orig)(gpr_clock_type clock_type) = gpr_now_impl; +static int g_time_shift_sec = 0; +static int g_time_shift_nsec = 0; +static gpr_timespec now_impl(gpr_clock_type clock) { + auto ts = gpr_now_impl_orig(clock); + // We only manipulate the realtime clock to simulate changes in wall-clock + // time + if (clock != GPR_CLOCK_REALTIME) { + return ts; + } + GPR_ASSERT(ts.tv_nsec >= 0); + GPR_ASSERT(ts.tv_nsec < GPR_NS_PER_SEC); + gpr_mu_lock(&g_mu); + ts.tv_sec += g_time_shift_sec; + ts.tv_nsec += g_time_shift_nsec; + gpr_mu_unlock(&g_mu); + if (ts.tv_nsec >= GPR_NS_PER_SEC) { + ts.tv_nsec -= GPR_NS_PER_SEC; + ++ts.tv_sec; + } else if (ts.tv_nsec < 0) { + --ts.tv_sec; + ts.tv_nsec = GPR_NS_PER_SEC + ts.tv_nsec; + } + return ts; +} + +// offset the value returned by gpr_now(GPR_CLOCK_REALTIME) by msecs +// milliseconds +static void set_now_offset(int msecs) { + g_time_shift_sec = msecs / 1000; + g_time_shift_nsec = (msecs % 1000) * 1e6; +} + +// restore the original implementation of gpr_now() +static void reset_now_offset() { + g_time_shift_sec = 0; + g_time_shift_nsec = 0; +} + +namespace grpc { +namespace testing { + +namespace { + +// gpr_now() is called with invalid clock_type +TEST(TimespecTest, GprNowInvalidClockType) { + // initialize to some junk value + gpr_clock_type invalid_clock_type = (gpr_clock_type)32641; + EXPECT_DEATH(gpr_now(invalid_clock_type), ".*"); +} + +// Add timespan with negative nanoseconds +TEST(TimespecTest, GprTimeAddNegativeNs) { + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; + EXPECT_DEATH(gpr_time_add(now, bad_ts), ".*"); +} + +// Subtract timespan with negative nanoseconds +TEST(TimespecTest, GprTimeSubNegativeNs) { + // Nanoseconds must always be positive. Negative timestamps are represented by + // (negative seconds, positive nanoseconds) + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; + EXPECT_DEATH(gpr_time_sub(now, bad_ts), ".*"); +} + +// Add negative milliseconds to gpr_timespec +TEST(TimespecTest, GrpcNegativeMillisToTimespec) { + // -1500 milliseconds converts to timespec (-2 secs, 5 * 10^8 nsec) + gpr_timespec ts = grpc_millis_to_timespec(-1500, GPR_CLOCK_MONOTONIC); + GPR_ASSERT(ts.tv_sec = -2); + GPR_ASSERT(ts.tv_nsec = 5e8); + GPR_ASSERT(ts.clock_type == GPR_CLOCK_MONOTONIC); +} + +class TimeChangeTest : public ::testing::Test { + protected: + TimeChangeTest() {} + + void SetUp() { + auto port = grpc_pick_unused_port_or_die(); + std::ostringstream addr_stream; + addr_stream << "localhost:" << port; + auto addr = addr_stream.str(); + server_.reset(new SubProcess({ + g_root + "/client_crash_test_server", + "--address=" + addr, + })); + GPR_ASSERT(server_); + channel_ = CreateChannel(addr, InsecureChannelCredentials()); + GPR_ASSERT(channel_); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void TearDown() { + server_.reset(); + reset_now_offset(); + } + + std::unique_ptr CreateStub() { + return grpc::testing::EchoTestService::NewStub(channel_); + } + + std::shared_ptr GetChannel() { return channel_; } + // time jump offsets in milliseconds + const int TIME_OFFSET1 = 20123; + const int TIME_OFFSET2 = 5678; + + private: + std::unique_ptr server_; + std::shared_ptr channel_; + std::unique_ptr stub_; +}; + +// Wall-clock time jumps forward on client before bidi stream is created +TEST_F(TimeChangeTest, TimeJumpForwardBeforeStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + // time jumps forward by TIME_OFFSET1 milliseconds + set_now_offset(TIME_OFFSET1); + auto stream = stub->BidiStream(&context); + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps back on client before bidi stream is created +TEST_F(TimeChangeTest, TimeJumpBackBeforeStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + // time jumps back by TIME_OFFSET1 milliseconds + set_now_offset(-TIME_OFFSET1); + auto stream = stub->BidiStream(&context); + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(request.message(), response.message()); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward on client while call is in progress +TEST_F(TimeChangeTest, TimeJumpForwardAfterStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + + // time jumps forward by TIME_OFFSET1 milliseconds. + set_now_offset(TIME_OFFSET1); + + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps back on client while call is in progress +TEST_F(TimeChangeTest, TimeJumpBackAfterStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + + // time jumps back TIME_OFFSET1 milliseconds. + set_now_offset(-TIME_OFFSET1); + + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward on client before connection to server is up +TEST_F(TimeChangeTest, TimeJumpForwardBeforeServerConnect) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + // time jumps forward by TIME_OFFSET2 milliseconds + set_now_offset(TIME_OFFSET2); + + auto ret = + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000)); + // We use monotonic clock for pthread_cond_timedwait() deadline on linux, and + // realtime clock on other platforms - see gpr_cv_wait() in sync_posix.cc. + // So changes in system clock affect deadlines on non-linux platforms +#ifdef GPR_LINUX + EXPECT_TRUE(ret); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +#else + EXPECT_FALSE(ret); +#endif +} + +// Wall-clock time jumps back on client before connection to server is up +TEST_F(TimeChangeTest, TimeJumpBackBeforeServerConnect) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward and backwards during call +TEST_F(TimeChangeTest, TimeJumpForwardAndBackDuringCall) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + + // time jumps forward by TIME_OFFSET milliseconds + set_now_offset(TIME_OFFSET1); + + EXPECT_TRUE(stream->Write(request)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->WritesDone()); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->Read(&response)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +} // namespace + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + std::string me = argv[0]; + // get index of last slash in path to test binary + auto lslash = me.rfind('/'); + // set g_root = path to directory containing test binary + if (lslash != std::string::npos) { + g_root = me.substr(0, lslash); + } else { + g_root = "."; + } + + gpr_mu_init(&g_mu); + gpr_now_impl = now_impl; + + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + auto ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index ff9d8873858..b473b7d7aa5 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -16,19 +16,19 @@ * */ -#include "test/cpp/util/channel_trace_proto_helper.h" +#include -#include -#include +#include "test/cpp/util/channel_trace_proto_helper.h" #include #include +#include +#include #include #include "src/proto/grpc/channelz/channelz.pb.h" namespace grpc { -namespace testing { namespace { @@ -37,25 +37,24 @@ namespace { // according to https://developers.google.com/protocol-buffers/docs/proto3#json template void VaidateProtoJsonTranslation(char* json_c_str) { - std::string json_str(json_c_str); + grpc::string json_str(json_c_str); Message msg; - google::protobuf::util::JsonParseOptions parse_options; + grpc::protobuf::json::JsonParseOptions parse_options; // If the following line is failing, then uncomment the last line of the // comment, and uncomment the lines that print the two strings. You can // then compare the output, and determine what fields are missing. // // parse_options.ignore_unknown_fields = true; - EXPECT_EQ(google::protobuf::util::JsonStringToMessage(json_str, &msg, - parse_options), - google::protobuf::util::Status::OK); - std::string proto_json_str; - google::protobuf::util::JsonPrintOptions print_options; + grpc::protobuf::util::Status s = + grpc::protobuf::json::JsonStringToMessage(json_str, &msg, parse_options); + EXPECT_TRUE(s.ok()); + grpc::string proto_json_str; + grpc::protobuf::json::JsonPrintOptions print_options; // We usually do not want this to be true, however it can be helpful to // uncomment and see the output produced then all fields are printed. // print_options.always_print_primitive_fields = true; - EXPECT_EQ(google::protobuf::util::MessageToJsonString(msg, &proto_json_str, - print_options), - google::protobuf::util::Status::OK); + s = grpc::protobuf::json::MessageToJsonString(msg, &proto_json_str); + EXPECT_TRUE(s.ok()); // uncomment these to compare the the json strings. // gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str()); // gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str()); @@ -64,6 +63,8 @@ void VaidateProtoJsonTranslation(char* json_c_str) { } // namespace +namespace testing { + void ValidateChannelTraceProtoJsonTranslation(char* json_c_str) { VaidateProtoJsonTranslation(json_c_str); } diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 22d5d7c71c2..7dee0051176 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -52,8 +52,9 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O /usr/local/bin/bazel -RUN chmod 755 /usr/local/bin/bazel +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ + bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ + rm bazel-0.20.0-installer-linux-x86_64.sh RUN mkdir -p /var/local/jenkins diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index aeee02a50fa..7a6fbfee7f4 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -94,6 +94,14 @@ ENV CLANG_FORMAT=clang-format RUN ln -s /clang+llvm-5.0.0-linux-x86_64-ubuntu14.04/bin/clang-tidy /usr/local/bin/clang-tidy ENV CLANG_TIDY=clang-tidy +#======================== +# Bazel installation + +RUN apt-get update && apt-get install -y wget && apt-get clean +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ + bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ + rm bazel-0.20.0-installer-linux-x86_64.sh + # Define the default command. CMD ["bash"] diff --git a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh index 28c49a66f24..903166122eb 100755 --- a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh +++ b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh @@ -22,7 +22,7 @@ cd "$(dirname "$0")" CLOUD_PROJECT=grpc-testing ZONE=us-central1-b # this zone allows 32core machines -LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v3 # update if newer image exists +LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v4 # update if newer image exists INSTANCE_NAME="${1:-grpc-kokoro-performance-server}" MACHINE_TYPE="${2:-n1-standard-32}" diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh index d67ff58506f..1bf2228279e 100755 --- a/tools/gce/linux_kokoro_performance_worker_init.sh +++ b/tools/gce/linux_kokoro_performance_worker_init.sh @@ -215,6 +215,11 @@ sudo mkdir /tmpfs sudo chown kbuilder /tmpfs touch /tmpfs/READY +# Disable automatic updates to prevent spurious apt-get install failures +# See https://github.com/grpc/grpc/issues/17794 +sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/10periodic +sudo sed -i 's/APT::Periodic::AutocleanInterval "1"/APT::Periodic::AutocleanInterval "0"/' /etc/apt/apt.conf.d/10periodic + # Restart for VM to pick up kernel update echo 'Successfully initialized the linux worker, going for reboot in 10 seconds' sleep 10 diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc index b66ac38942f..ff5593e031a 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc @@ -21,13 +21,7 @@ ulimit -c unlimited # Performance PR testing needs GH API key and PR metadata to comment results if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ]; then - retry=0 - until [ $retry -ge 3 ] - do - sudo apt-get install -y jq && break - retry=$[$retry+1] - sleep 5 - done + sudo apt-get install -y jq export ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) fi diff --git a/tools/internal_ci/linux/grpc_run_tests_matrix.sh b/tools/internal_ci/linux/grpc_run_tests_matrix.sh index f8fd963ccf3..f9acd814ae8 100755 --- a/tools/internal_ci/linux/grpc_run_tests_matrix.sh +++ b/tools/internal_ci/linux/grpc_run_tests_matrix.sh @@ -23,13 +23,7 @@ source tools/internal_ci/helper_scripts/prepare_build_linux_rc # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then sudo apt-get update - retry=0 - until [ $retry -ge 3 ] - do - sudo apt-get install -y jq && break - retry=$[$retry+1] - sleep 5 - done + sudo apt-get install -y jq ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch" fi diff --git a/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg b/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg index dc35ce81ffd..f639b4ef77c 100644 --- a/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg +++ b/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg @@ -16,7 +16,7 @@ # Location of the continuous shell script in repository. build_file: "grpc/tools/internal_ci/macos/grpc_ios_binary_size.sh" -timeout_mins: 60 +timeout_mins: 90 before_action { fetch_keystore { keystore_resource { diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 9e07c548b69..6693fcec58e 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -271,6 +271,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "close_fd_test", + "src": [ + "test/core/bad_connection/close_fd_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -4894,6 +4910,24 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "time_change_test", + "src": [ + "test/cpp/end2end/time_change_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index b41fef6b795..f35be0c1f43 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -311,6 +311,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "close_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -5548,6 +5572,28 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "time_change_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, diff --git a/tools/run_tests/performance/OWNERS b/tools/run_tests/performance/OWNERS deleted file mode 100644 index 9cf8c131111..00000000000 --- a/tools/run_tests/performance/OWNERS +++ /dev/null @@ -1,9 +0,0 @@ -set noparent - -# These owners are in place to ensure that scenario_result_schema.json is not -# modified without also running tools/run_tests/performance/patch_scenario_results_schema.py -# to update the BigQuery schema - -@ncteisen -@apolcyn -@jtattermusch diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 603977545ce..11bd959052e 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -229,7 +229,7 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_GOOGLE_DEFAULT_CREDS + return [] def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -254,7 +254,7 @@ class JavaOkHttpClient: return {} def unimplemented_test_cases(self): - return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS + return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE def __str__(self): return 'javaokhttp' @@ -285,7 +285,7 @@ class GoLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_GOOGLE_DEFAULT_CREDS + return _SKIP_COMPRESSION def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION