aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/lock.yml2
-rw-r--r--BUILD3
-rw-r--r--CMakeLists.txt77
-rw-r--r--Makefile82
-rw-r--r--bazel/grpc_build_system.bzl2
-rw-r--r--build.yaml91
-rw-r--r--config.m41
-rw-r--r--config.w321
-rw-r--r--doc/core/grpc-client-server-polling-engine-usage.md32
-rw-r--r--doc/core/grpc-cq.md64
-rw-r--r--doc/core/grpc-polling-engines.md154
-rw-r--r--doc/images/grpc-call-channel-cq.pngbin0 -> 46078 bytes
-rw-r--r--doc/images/grpc-client-lb-pss.pngbin0 -> 56397 bytes
-rw-r--r--doc/images/grpc-cq.pngbin0 -> 41659 bytes
-rw-r--r--doc/images/grpc-epoll1.pngbin0 -> 36205 bytes
-rw-r--r--doc/images/grpc-epollex.pngbin0 -> 52651 bytes
-rw-r--r--doc/images/grpc-ps-pss-fd.pngbin0 -> 24969 bytes
-rw-r--r--doc/images/grpc-pss.pngbin0 -> 31518 bytes
-rw-r--r--doc/images/grpc-server-cq-fds.pngbin0 -> 42096 bytes
-rw-r--r--examples/python/interceptors/default_value/default_value_client_interceptor.py2
-rw-r--r--gRPC-C++.podspec3
-rw-r--r--gRPC-Core.podspec6
-rw-r--r--grpc.def1
-rw-r--r--grpc.gemspec2
-rw-r--r--grpc.gyp16
-rw-r--r--include/grpc/grpc.h7
-rw-r--r--include/grpc/grpc_security.h4
-rw-r--r--include/grpc/impl/codegen/grpc_types.h15
-rw-r--r--include/grpcpp/impl/codegen/callback_common.h93
-rw-r--r--include/grpcpp/impl/codegen/client_callback.h2
-rw-r--r--package.xml2
-rw-r--r--src/compiler/cpp_generator.cc148
-rw-r--r--src/core/ext/filters/client_channel/client_channel_channelz.cc11
-rw-r--r--src/core/ext/filters/client_channel/connector.h3
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc6
-rw-r--r--src/core/ext/filters/client_channel/lb_policy_factory.h6
-rw-r--r--src/core/ext/filters/client_channel/subchannel.cc16
-rw-r--r--src/core/ext/filters/client_channel/subchannel.h8
-rw-r--r--src/core/ext/filters/http/client/http_client_filter.cc19
-rw-r--r--src/core/ext/filters/http/server/http_server_filter.cc18
-rw-r--r--src/core/ext/filters/message_size/message_size_filter.cc26
-rw-r--r--src/core/ext/transport/chttp2/client/chttp2_connector.cc2
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.cc33
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.h2
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_data.cc4
-rw-r--r--src/core/ext/transport/chttp2/transport/internal.h8
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.cc139
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.cc6
-rw-r--r--src/core/lib/channel/channelz.cc110
-rw-r--r--src/core/lib/channel/channelz.h36
-rw-r--r--src/core/lib/channel/channelz_registry.cc18
-rw-r--r--src/core/lib/iomgr/error.cc26
-rw-r--r--src/core/lib/iomgr/ev_epoll1_linux.cc4
-rw-r--r--src/core/lib/iomgr/ev_epollex_linux.cc4
-rw-r--r--src/core/lib/iomgr/ev_epollsig_linux.cc1743
-rw-r--r--src/core/lib/iomgr/ev_epollsig_linux.h35
-rw-r--r--src/core/lib/iomgr/ev_posix.cc17
-rw-r--r--src/core/lib/iomgr/port.h2
-rw-r--r--src/core/lib/iomgr/tcp_posix.cc7
-rw-r--r--src/core/lib/iomgr/timer_generic.cc2
-rw-r--r--src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc3
-rw-r--r--src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc3
-rw-r--r--src/core/lib/security/transport/server_auth_filter.cc40
-rw-r--r--src/core/lib/surface/completion_queue.cc34
-rw-r--r--src/core/lib/surface/completion_queue.h19
-rw-r--r--src/core/lib/surface/completion_queue_factory.cc6
-rw-r--r--src/core/lib/surface/server.cc42
-rw-r--r--src/cpp/client/channel_cc.cc28
-rw-r--r--src/cpp/common/callback_common.cc149
-rw-r--r--src/cpp/server/channelz/channelz_service.cc17
-rw-r--r--src/cpp/server/channelz/channelz_service.h4
-rw-r--r--src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs119
-rw-r--r--src/csharp/Grpc.Core.Tests/MarshallerTest.cs105
-rw-r--r--src/csharp/Grpc.Core.Tests/MetadataTest.cs17
-rw-r--r--src/csharp/Grpc.Core/ClientBase.cs20
-rw-r--r--src/csharp/Grpc.Core/DeserializationContext.cs46
-rw-r--r--src/csharp/Grpc.Core/Internal/MarshalUtils.cs7
-rw-r--r--src/csharp/Grpc.Core/Marshaller.cs126
-rw-r--r--src/csharp/Grpc.Core/Metadata.cs50
-rw-r--r--src/csharp/Grpc.Core/SerializationContext.cs34
-rwxr-xr-xsrc/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj2
-rw-r--r--src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj2
-rw-r--r--src/csharp/tests.json2
-rw-r--r--src/objective-c/BoringSSL-GRPC.podspec5
-rw-r--r--src/objective-c/GRPCClient/private/NSError+GRPC.h2
-rw-r--r--src/objective-c/GRPCClient/private/NSError+GRPC.m20
-rw-r--r--src/objective-c/tests/CronetUnitTests/CronetUnitTests.m2
-rw-r--r--src/objective-c/tests/Podfile1
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/project.pbxproj257
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme92
-rw-r--r--src/objective-c/tests/UnitTests/Info.plist22
-rw-r--r--src/objective-c/tests/UnitTests/UnitTests.m62
-rwxr-xr-xsrc/objective-c/tests/run_tests.sh10
-rw-r--r--src/php/tests/unit_tests/ChannelTest.php4
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c2
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h9
-rwxr-xr-xsrc/ruby/pb/test/client.rb14
-rw-r--r--templates/README.md39
-rw-r--r--templates/gRPC-Core.podspec.template3
-rw-r--r--templates/src/objective-c/BoringSSL-GRPC.podspec.template5
-rwxr-xr-xtest/core/end2end/generate_tests.bzl564
-rw-r--r--test/core/end2end/inproc_callback_test.cc31
-rw-r--r--test/core/iomgr/BUILD32
-rw-r--r--test/core/iomgr/ev_epollsig_linux_test.cc321
-rw-r--r--test/core/iomgr/pollset_set_test.cc447
-rw-r--r--test/core/surface/completion_queue_test.cc25
-rw-r--r--test/core/surface/public_headers_must_be_c89.c1
-rw-r--r--test/core/tsi/alts/fake_handshaker/BUILD5
-rw-r--r--test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc31
-rw-r--r--test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h29
-rw-r--r--test/core/tsi/alts/fake_handshaker/fake_handshaker_server_main.cc53
-rw-r--r--test/cpp/codegen/compiler_test_golden50
-rw-r--r--test/cpp/end2end/channelz_service_test.cc152
-rw-r--r--test/cpp/end2end/client_callback_end2end_test.cc111
-rw-r--r--test/cpp/microbenchmarks/bm_chttp2_hpack.cc74
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc2
-rw-r--r--test/cpp/microbenchmarks/fullstack_fixtures.h1
-rw-r--r--test/cpp/microbenchmarks/helpers.h1
-rw-r--r--tools/dockerfile/grpc_artifact_linux_x64/Dockerfile18
-rw-r--r--tools/dockerfile/grpc_artifact_linux_x86/Dockerfile9
-rw-r--r--tools/doxygen/Doxyfile.c++.internal2
-rw-r--r--tools/doxygen/Doxyfile.core3
-rw-r--r--tools/doxygen/Doxyfile.core.internal5
-rwxr-xr-xtools/internal_ci/helper_scripts/delete_nonartifacts.sh2
-rw-r--r--tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_basictests_multilang.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_build_artifacts.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_build_artifacts_extra.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_build_packages.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_coverage.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_distribtests.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_distribtests_standalone.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_full_performance_master.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_full_performance_release.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_interop_alts.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_interop_matrix.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_interop_tocloud.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_interop_toprod.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_portability.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_portability_build_only.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_publish_packages.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_pull_request_sanity.cfg2
-rw-r--r--tools/internal_ci/linux/grpc_sanity.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_sanity.cfg2
-rw-r--r--tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg2
-rw-r--r--tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg2
-rw-r--r--tools/internal_ci/macos/grpc_basictests_dbg.cfg2
-rw-r--r--tools/internal_ci/macos/grpc_basictests_opt.cfg2
-rw-r--r--tools/internal_ci/macos/grpc_build_artifacts.cfg2
-rw-r--r--tools/internal_ci/macos/grpc_distribtests.cfg2
-rw-r--r--tools/internal_ci/macos/grpc_interop.cfg2
-rw-r--r--tools/internal_ci/macos/grpc_interop_toprod.cfg2
-rw-r--r--tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg2
-rw-r--r--tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg2
-rw-r--r--tools/internal_ci/macos/pull_request/grpc_interop.cfg2
-rw-r--r--tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_basictests.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_basictests_dbg.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_basictests_opt.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_build_artifacts.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_build_packages.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_distribtests.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_distribtests_standalone.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_portability.cfg2
-rw-r--r--tools/internal_ci/windows/grpc_portability_build_only.cfg2
-rw-r--r--tools/internal_ci/windows/pull_request/grpc_basictests.cfg2
-rw-r--r--tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg2
-rw-r--r--tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg2
-rw-r--r--tools/internal_ci/windows/pull_request/grpc_portability.cfg2
-rw-r--r--tools/run_tests/generated/sources_and_headers.json51
-rw-r--r--tools/run_tests/generated/tests.json40
-rwxr-xr-xtools/run_tests/python_utils/jobset.py23
-rwxr-xr-xtools/run_tests/run_interop_tests.py28
-rwxr-xr-xtools/run_tests/run_tests.py4
-rwxr-xr-xtools/run_tests/run_tests_matrix.py19
202 files changed, 3022 insertions, 3800 deletions
diff --git a/.github/lock.yml b/.github/lock.yml
new file mode 100644
index 0000000000..119e4840be
--- /dev/null
+++ b/.github/lock.yml
@@ -0,0 +1,2 @@
+daysUntilLock: 90
+lockComment: false
diff --git a/BUILD b/BUILD
index 271e57e36c..0cd587a274 100644
--- a/BUILD
+++ b/BUILD
@@ -119,7 +119,6 @@ GRPCXX_SRCS = [
"src/cpp/client/credentials_cc.cc",
"src/cpp/client/generic_stub.cc",
"src/cpp/common/alarm.cc",
- "src/cpp/common/callback_common.cc",
"src/cpp/common/channel_arguments.cc",
"src/cpp/common/channel_filter.cc",
"src/cpp/common/completion_queue_cc.cc",
@@ -708,7 +707,6 @@ grpc_cc_library(
"src/core/lib/iomgr/error.cc",
"src/core/lib/iomgr/ev_epoll1_linux.cc",
"src/core/lib/iomgr/ev_epollex_linux.cc",
- "src/core/lib/iomgr/ev_epollsig_linux.cc",
"src/core/lib/iomgr/ev_poll_posix.cc",
"src/core/lib/iomgr/ev_posix.cc",
"src/core/lib/iomgr/ev_windows.cc",
@@ -860,7 +858,6 @@ grpc_cc_library(
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
- "src/core/lib/iomgr/ev_epollsig_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c358e9bd43..b0e2244e75 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -253,9 +253,6 @@ add_dependencies(buildtests_c error_test)
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c ev_epollex_linux_test)
endif()
-if(_gRPC_PLATFORM_LINUX)
-add_dependencies(buildtests_c ev_epollsig_linux_test)
-endif()
add_dependencies(buildtests_c fake_resolver_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fake_transport_security_test)
@@ -355,9 +352,6 @@ add_dependencies(buildtests_c no_server_test)
add_dependencies(buildtests_c num_external_connectivity_watchers_test)
add_dependencies(buildtests_c parse_address_test)
add_dependencies(buildtests_c percent_encoding_test)
-if(_gRPC_PLATFORM_LINUX)
-add_dependencies(buildtests_c pollset_set_test)
-endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c resolve_address_posix_test)
endif()
@@ -974,7 +968,6 @@ add_library(grpc
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_epollsig_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/ev_windows.cc
@@ -1382,7 +1375,6 @@ add_library(grpc_cronet
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_epollsig_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/ev_windows.cc
@@ -1776,7 +1768,6 @@ add_library(grpc_test_util
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_epollsig_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/ev_windows.cc
@@ -2086,7 +2077,6 @@ add_library(grpc_test_util_unsecure
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_epollsig_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/ev_windows.cc
@@ -2375,7 +2365,6 @@ add_library(grpc_unsecure
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_epollsig_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/ev_windows.cc
@@ -2773,7 +2762,6 @@ add_library(grpc++
src/cpp/client/credentials_cc.cc
src/cpp/client/generic_stub.cc
src/cpp/common/alarm.cc
- src/cpp/common/callback_common.cc
src/cpp/common/channel_arguments.cc
src/cpp/common/channel_filter.cc
src/cpp/common/completion_queue_cc.cc
@@ -3135,7 +3123,6 @@ add_library(grpc++_cronet
src/cpp/client/credentials_cc.cc
src/cpp/client/generic_stub.cc
src/cpp/common/alarm.cc
- src/cpp/common/callback_common.cc
src/cpp/common/channel_arguments.cc
src/cpp/common/channel_filter.cc
src/cpp/common/completion_queue_cc.cc
@@ -3222,7 +3209,6 @@ add_library(grpc++_cronet
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_epollsig_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
src/core/lib/iomgr/ev_posix.cc
src/core/lib/iomgr/ev_windows.cc
@@ -4261,7 +4247,6 @@ add_library(grpc++_unsecure
src/cpp/client/credentials_cc.cc
src/cpp/client/generic_stub.cc
src/cpp/common/alarm.cc
- src/cpp/common/callback_common.cc
src/cpp/common/channel_arguments.cc
src/cpp/common/channel_filter.cc
src/cpp/common/completion_queue_cc.cc
@@ -6393,37 +6378,6 @@ target_link_libraries(ev_epollex_linux_test
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX)
-
-add_executable(ev_epollsig_linux_test
- test/core/iomgr/ev_epollsig_linux_test.cc
-)
-
-
-target_include_directories(ev_epollsig_linux_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(ev_epollsig_linux_test
- ${_gRPC_ALLTARGETS_LIBRARIES}
- grpc_test_util
- grpc
- gpr_test_util
- gpr
-)
-
-endif()
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
add_executable(fake_resolver_test
test/core/client_channel/resolvers/fake_resolver_test.cc
@@ -8508,37 +8462,6 @@ target_link_libraries(percent_encoding_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
-if(_gRPC_PLATFORM_LINUX)
-
-add_executable(pollset_set_test
- test/core/iomgr/pollset_set_test.cc
-)
-
-
-target_include_directories(pollset_set_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(pollset_set_test
- ${_gRPC_ALLTARGETS_LIBRARIES}
- grpc_test_util
- grpc
- gpr_test_util
- gpr
-)
-
-endif()
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(resolve_address_posix_test
diff --git a/Makefile b/Makefile
index 2f2537228c..e86a0695be 100644
--- a/Makefile
+++ b/Makefile
@@ -352,6 +352,7 @@ CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
CXXFLAGS += -stdlib=libc++
endif
+CXXFLAGS += -Wnon-virtual-dtor
CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1 -Wno-deprecated-declarations -Ithird_party/nanopb -DPB_FIELD_32BIT
COREFLAGS += -fno-rtti -fno-exceptions
LDFLAGS += -g
@@ -997,7 +998,6 @@ dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
error_test: $(BINDIR)/$(CONFIG)/error_test
ev_epollex_linux_test: $(BINDIR)/$(CONFIG)/ev_epollex_linux_test
-ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
fake_transport_security_test: $(BINDIR)/$(CONFIG)/fake_transport_security_test
fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test
@@ -1079,7 +1079,6 @@ parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test
-pollset_set_test: $(BINDIR)/$(CONFIG)/pollset_set_test
resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test
resolve_address_using_ares_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test
resolve_address_using_native_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test
@@ -1454,7 +1453,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/endpoint_pair_test \
$(BINDIR)/$(CONFIG)/error_test \
$(BINDIR)/$(CONFIG)/ev_epollex_linux_test \
- $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \
$(BINDIR)/$(CONFIG)/fake_resolver_test \
$(BINDIR)/$(CONFIG)/fake_transport_security_test \
$(BINDIR)/$(CONFIG)/fd_conservation_posix_test \
@@ -1524,7 +1522,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test \
$(BINDIR)/$(CONFIG)/parse_address_test \
$(BINDIR)/$(CONFIG)/percent_encoding_test \
- $(BINDIR)/$(CONFIG)/pollset_set_test \
$(BINDIR)/$(CONFIG)/resolve_address_posix_test \
$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test \
$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test \
@@ -1991,8 +1988,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 )
$(E) "[RUN] Testing ev_epollex_linux_test"
$(Q) $(BINDIR)/$(CONFIG)/ev_epollex_linux_test || ( echo test ev_epollex_linux_test failed ; exit 1 )
- $(E) "[RUN] Testing ev_epollsig_linux_test"
- $(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 )
$(E) "[RUN] Testing fake_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/fake_resolver_test || ( echo test fake_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing fake_transport_security_test"
@@ -2119,8 +2114,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 )
$(E) "[RUN] Testing percent_encoding_test"
$(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 )
- $(E) "[RUN] Testing pollset_set_test"
- $(Q) $(BINDIR)/$(CONFIG)/pollset_set_test || ( echo test pollset_set_test failed ; exit 1 )
$(E) "[RUN] Testing resolve_address_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 )
$(E) "[RUN] Testing resolve_address_using_ares_resolver_test"
@@ -3483,7 +3476,6 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
@@ -3890,7 +3882,6 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
@@ -4282,7 +4273,6 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
@@ -4583,7 +4573,6 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
@@ -4850,7 +4839,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
@@ -5228,7 +5216,6 @@ LIBGRPC++_SRC = \
src/cpp/client/credentials_cc.cc \
src/cpp/client/generic_stub.cc \
src/cpp/common/alarm.cc \
- src/cpp/common/callback_common.cc \
src/cpp/common/channel_arguments.cc \
src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue_cc.cc \
@@ -5598,7 +5585,6 @@ LIBGRPC++_CRONET_SRC = \
src/cpp/client/credentials_cc.cc \
src/cpp/client/generic_stub.cc \
src/cpp/common/alarm.cc \
- src/cpp/common/callback_common.cc \
src/cpp/common/channel_arguments.cc \
src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue_cc.cc \
@@ -5685,7 +5671,6 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
@@ -6682,7 +6667,6 @@ LIBGRPC++_UNSECURE_SRC = \
src/cpp/client/credentials_cc.cc \
src/cpp/client/generic_stub.cc \
src/cpp/common/alarm.cc \
- src/cpp/common/callback_common.cc \
src/cpp/common/channel_arguments.cc \
src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue_cc.cc \
@@ -11350,38 +11334,6 @@ endif
endif
-EV_EPOLLSIG_LINUX_TEST_SRC = \
- test/core/iomgr/ev_epollsig_linux_test.cc \
-
-EV_EPOLLSIG_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLLSIG_LINUX_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test: $(EV_EPOLLSIG_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
- $(E) "[LD] Linking $@"
- $(Q) mkdir -p `dirname $@`
- $(Q) $(LD) $(LDFLAGS) $(EV_EPOLLSIG_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/iomgr/ev_epollsig_linux_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_ev_epollsig_linux_test: $(EV_EPOLLSIG_LINUX_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(EV_EPOLLSIG_LINUX_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
FAKE_RESOLVER_TEST_SRC = \
test/core/client_channel/resolvers/fake_resolver_test.cc \
@@ -13992,38 +13944,6 @@ endif
endif
-POLLSET_SET_TEST_SRC = \
- test/core/iomgr/pollset_set_test.cc \
-
-POLLSET_SET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(POLLSET_SET_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/pollset_set_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/pollset_set_test: $(POLLSET_SET_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
- $(E) "[LD] Linking $@"
- $(Q) mkdir -p `dirname $@`
- $(Q) $(LD) $(LDFLAGS) $(POLLSET_SET_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/pollset_set_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/iomgr/pollset_set_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_pollset_set_test: $(POLLSET_SET_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(POLLSET_SET_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
RESOLVE_ADDRESS_POSIX_TEST_SRC = \
test/core/iomgr/resolve_address_posix_test.cc \
diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl
index b3f97650e8..159ebd5d1f 100644
--- a/bazel/grpc_build_system.bzl
+++ b/bazel/grpc_build_system.bzl
@@ -24,7 +24,7 @@
#
# The set of pollers to test against if a test exercises polling
-POLLERS = ["epollex", "epollsig", "epoll1", "poll", "poll-cv"]
+POLLERS = ["epollex", "epoll1", "poll", "poll-cv"]
def if_not_windows(a):
return select({
diff --git a/build.yaml b/build.yaml
index d6e67aa7ee..3bc78d9299 100644
--- a/build.yaml
+++ b/build.yaml
@@ -266,7 +266,6 @@ filegroups:
- src/core/lib/iomgr/error.cc
- src/core/lib/iomgr/ev_epoll1_linux.cc
- src/core/lib/iomgr/ev_epollex_linux.cc
- - src/core/lib/iomgr/ev_epollsig_linux.cc
- src/core/lib/iomgr/ev_poll_posix.cc
- src/core/lib/iomgr/ev_posix.cc
- src/core/lib/iomgr/ev_windows.cc
@@ -446,7 +445,6 @@ filegroups:
- src/core/lib/iomgr/error_internal.h
- src/core/lib/iomgr/ev_epoll1_linux.h
- src/core/lib/iomgr/ev_epollex_linux.h
- - src/core/lib/iomgr/ev_epollsig_linux.h
- src/core/lib/iomgr/ev_poll_posix.h
- src/core/lib/iomgr/ev_posix.h
- src/core/lib/iomgr/exec_ctx.h
@@ -1327,7 +1325,6 @@ filegroups:
- src/cpp/client/credentials_cc.cc
- src/cpp/client/generic_stub.cc
- src/cpp/common/alarm.cc
- - src/cpp/common/callback_common.cc
- src/cpp/common/channel_arguments.cc
- src/cpp/common/channel_filter.cc
- src/cpp/common/completion_queue_cc.cc
@@ -1438,7 +1435,6 @@ libs:
filegroups:
- gpr_base
secure: false
- vs_project_guid: '{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}'
- name: gpr_test_util
build: private
language: c
@@ -1449,7 +1445,6 @@ libs:
deps:
- gpr
secure: false
- vs_project_guid: '{EAB0A629-17A9-44DB-B5FF-E91A721FE037}'
- name: grpc
build: all
language: c
@@ -1482,10 +1477,6 @@ libs:
- grpc_server_backward_compatibility
generate_plugin_registry: true
secure: true
- vs_packages:
- - grpc.dependencies.openssl
- - grpc.dependencies.zlib
- vs_project_guid: '{29D16885-7228-4C31-81ED-5F9187C7F2A9}'
- name: grpc_cronet
build: all
language: c
@@ -1502,27 +1493,6 @@ libs:
platforms:
- linux
secure: true
-- name: grpc_dll
- build: private
- language: c
- src: []
- deps:
- - gpr
- - grpc
- build_system:
- - visual_studio
- deps_linkage: static
- dll_def: grpc.def
- vs_config_type: DynamicLibrary
- vs_packages:
- - grpc.dependencies.openssl
- - grpc.dependencies.zlib
- vs_project_guid: '{A2F6CBBA-A553-41B3-A7DE-F26DECCC27F0}'
- vs_props:
- - zlib
- - openssl
- - winsock
- - global
- name: grpc_test_util
build: private
language: c
@@ -1541,7 +1511,6 @@ libs:
- grpc
filegroups:
- grpc_test_util_base
- vs_project_guid: '{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}'
- name: grpc_test_util_unsecure
build: private
language: c
@@ -1552,7 +1521,6 @@ libs:
filegroups:
- grpc_test_util_base
secure: false
- vs_project_guid: '{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}'
- name: grpc_unsecure
build: all
language: c
@@ -1583,7 +1551,6 @@ libs:
- grpc_server_backward_compatibility
generate_plugin_registry: true
secure: false
- vs_project_guid: '{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}'
- name: reconnect_server
build: private
language: c
@@ -1637,7 +1604,6 @@ libs:
- grpc++_codegen_proto
- grpc++_codegen_base_src
secure: check
- vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
- name: grpc++_core_stats
build: private
language: c++
@@ -1683,7 +1649,6 @@ libs:
deps:
- grpc++
baselib: true
- vs_project_guid: '{9F58AD72-49E1-4D10-B826-9E190AB0AAC0}'
- name: grpc++_proto_reflection_desc_db
build: private
language: c++
@@ -1796,7 +1761,6 @@ libs:
- grpc++_codegen_base
- grpc++_codegen_base_src
secure: false
- vs_project_guid: '{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}'
- name: grpc_benchmark
build: test
language: c++
@@ -1871,9 +1835,6 @@ libs:
filegroups:
- grpc++_config_proto
secure: false
- vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}'
- vs_props:
- - protoc
- name: grpcpp_channelz
build: all
language: c++
@@ -2028,16 +1989,6 @@ libs:
LDFLAGS: $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy)
deps_linkage: static
dll: only
- vs_config_type: DynamicLibrary
- vs_packages:
- - grpc.dependencies.openssl
- - grpc.dependencies.zlib
- vs_project_guid: '{D64C6D63-4458-4A88-AB38-35678384A7E4}'
- vs_props:
- - zlib
- - openssl
- - winsock
- - global
targets:
- name: algorithm_test
build: test
@@ -2371,21 +2322,6 @@ targets:
- uv
platforms:
- linux
-- name: ev_epollsig_linux_test
- cpu_cost: 3
- build: test
- language: c
- src:
- - test/core/iomgr/ev_epollsig_linux_test.cc
- deps:
- - grpc_test_util
- - grpc
- - gpr_test_util
- - gpr
- exclude_iomgrs:
- - uv
- platforms:
- - linux
- name: fake_resolver_test
build: test
language: c
@@ -3337,20 +3273,6 @@ targets:
- gpr_test_util
- gpr
uses_polling: false
-- name: pollset_set_test
- build: test
- language: c
- src:
- - test/core/iomgr/pollset_set_test.cc
- deps:
- - grpc_test_util
- - grpc
- - gpr_test_util
- - gpr
- exclude_iomgrs:
- - uv
- platforms:
- - linux
- name: resolve_address_posix_test
build: test
language: c
@@ -4762,8 +4684,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- vs_project_guid: '{7E51A25F-AC59-488F-906C-C60FAAE706AA}'
- name: grpc_csharp_plugin
build: protoc
language: c++
@@ -4772,8 +4692,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- vs_project_guid: '{3C813052-A49A-4662-B90A-1ADBEC7EE453}'
- name: grpc_linux_system_roots_test
gtest: true
build: test
@@ -4793,7 +4711,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- name: grpc_objective_c_plugin
build: protoc
language: c++
@@ -4802,8 +4719,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- vs_project_guid: '{19564640-CEE6-4921-ABA5-676ED79A36F6}'
- name: grpc_php_plugin
build: protoc
language: c++
@@ -4812,7 +4727,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- name: grpc_python_plugin
build: protoc
language: c++
@@ -4821,8 +4735,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- vs_project_guid: '{DF52D501-A6CF-4E6F-BA38-6EBE2E8DAFB2}'
- name: grpc_ruby_plugin
build: protoc
language: c++
@@ -4831,8 +4743,6 @@ targets:
deps:
- grpc_plugin_support
secure: false
- vs_config_type: Application
- vs_project_guid: '{069E9D05-B78B-4751-9252-D21EBAE7DE8E}'
- name: grpc_tool_test
gtest: true
build: test
@@ -5859,6 +5769,7 @@ defaults:
COREFLAGS: -fno-rtti -fno-exceptions
CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
-Wno-deprecated-declarations -Ithird_party/nanopb -DPB_FIELD_32BIT
+ CXXFLAGS: -Wnon-virtual-dtor
LDFLAGS: -g
zlib:
CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration
diff --git a/config.m4 b/config.m4
index af3624cdd1..b9862f34ab 100644
--- a/config.m4
+++ b/config.m4
@@ -118,7 +118,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
- src/core/lib/iomgr/ev_epollsig_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_posix.cc \
src/core/lib/iomgr/ev_windows.cc \
diff --git a/config.w32 b/config.w32
index ad91ee40bd..90a51057c4 100644
--- a/config.w32
+++ b/config.w32
@@ -93,7 +93,6 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\iomgr\\error.cc " +
"src\\core\\lib\\iomgr\\ev_epoll1_linux.cc " +
"src\\core\\lib\\iomgr\\ev_epollex_linux.cc " +
- "src\\core\\lib\\iomgr\\ev_epollsig_linux.cc " +
"src\\core\\lib\\iomgr\\ev_poll_posix.cc " +
"src\\core\\lib\\iomgr\\ev_posix.cc " +
"src\\core\\lib\\iomgr\\ev_windows.cc " +
diff --git a/doc/core/grpc-client-server-polling-engine-usage.md b/doc/core/grpc-client-server-polling-engine-usage.md
new file mode 100644
index 0000000000..3a560e71a8
--- /dev/null
+++ b/doc/core/grpc-client-server-polling-engine-usage.md
@@ -0,0 +1,32 @@
+# Polling Engine Usage on gRPC client and Server
+
+_Author: Sree Kuchibhotla (@sreecha) - Sep 2018_
+
+
+This document talks about how polling engine is used in gRPC core (both on client and server code paths).
+
+## gRPC client
+
+### Relation between Call, Channel (sub-channels), Completion queue, `grpc_pollset`
+- A gRPC Call is tied to a channel (more specifically a sub-channel) and a completion queue for the lifetime of the call.
+- Once a _sub-channel_ is picked for the call, the file-descriptor (socket fd in case of TCP channels) is added to the pollset corresponding to call's completion queue. (Recall that as per [grpc-cq](grpc-cq.md), a completion queue has a pollset by default)
+
+![image](../images/grpc-call-channel-cq.png)
+
+
+### Making progress on Async `connect()` on sub-channels (`grpc_pollset_set` usecase)
+- A gRPC channel is created between a client and a 'target'. The 'target' may resolve in to one or more backend servers.
+- A sub-channel is the 'connection' from a client to the backend server
+- While establishing sub-cannels (i.e connections) to the backends, gRPC issues async [`connect()`](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/iomgr/tcp_client_posix.cc#L296) calls which may not complete right away. When the `connect()` eventually succeeds, the socket fd is make 'writable'
+ - This means that the polling engine must be monitoring all these sub-channel `fd`s for writable events and we need to make sure there is a polling thread that monitors all these fds
+ - To accomplish this, the `grpc_pollset_set` is used the following way (see picture below)
+
+![image](../images/grpc-client-lb-pss.png)
+
+## gRPC server
+
+- The listening fd (i.e., the socket fd corresponding to the server listening port) is added to each of the server completion queues. Note that in gRPC we use SO_REUSEPORT option and create multiple listening fds but all of them map to the same listening port
+- A new incoming channel is assigned to some server completion queue picked randomly (note that we currently [round-robin](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/iomgr/tcp_server_posix.cc#L231) over the server completion queues)
+
+![image](../images/grpc-server-cq-fds.png)
+
diff --git a/doc/core/grpc-cq.md b/doc/core/grpc-cq.md
new file mode 100644
index 0000000000..b485c35456
--- /dev/null
+++ b/doc/core/grpc-cq.md
@@ -0,0 +1,64 @@
+# gRPC Completion Queue
+
+_Author: Sree Kuchibhotla (@sreecha) - Sep 2018_
+
+Code: [completion_queue.cc](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/surface/completion_queue.cc)
+
+This document gives an overview of completion queue architecture and focuses mainly on the interaction between completion queue and the Polling engine layer.
+
+## Completion queue attributes
+Completion queue has two attributes
+
+ - Completion_type:
+ - GRPC_CQ_NEXT: grpc_completion_queue_next() can be called (but not grpc_completion_queue_pluck())
+ - GRPC_CQ_PLUCK: grpc_completion_queue_pluck() can be called (but not grpc_completion_queue_next())
+ - GRPC_CQ_CALLBACK: The tags in the queue are function pointers to callbacks. Also, neither next() nor pluck() can be called on this
+
+ - Polling_type:
+ - GRPC_CQ_NON_POLLING: Threads calling completion_queue_next/pluck do not do any polling
+ - GRPC_CQ_DEFAULT_POLLING: Threads calling completion_queue_next/pluck do polling
+ - GRPC_CQ_NON_LISTENING: Functionally similar to default polling except for a boolean attribute that states that the cq is non-listening. This is used by the grpc-server code to not associate any listening sockets with this completion-queue’s pollset
+
+
+## Details
+
+![image](../images/grpc-cq.png)
+
+
+### **grpc\_completion\_queue\_next()** & **grpc_completion_queue_pluck()** APIS
+
+
+``` C++
+grpc_completion_queue_next(cq, deadline)/pluck(cq, deadline, tag) {
+ while(true) {
+ \\ 1. If an event is queued in the completion queue, dequeue and return
+ \\ (in case of pluck() dequeue only if the tag is the one we are interested in)
+
+ \\ 2. If completion queue shutdown return
+
+ \\ 3. In case of pluck, add (tag, worker) pair to the tag<->worker map on the cq
+
+ \\ 4. Call grpc_pollset_work(cq’s-pollset, deadline) to do polling
+ \\ Note that if this function found some fds to be readable/writable/error,
+ \\ it would have scheduled those closures (which may queue completion events
+ \\ on SOME completion queue - not necessarily this one)
+ }
+}
+```
+
+### Queuing a completion event (i.e., "tag")
+
+``` C++
+grpc_cq_end_op(cq, tag) {
+ \\ 1. Queue the tag in the event queue
+
+ \\ 2. Find the pollset corresponding to the completion queue
+ \\ (i) If the cq is of type GRPC_CQ_NEXT, then KICK ANY worker
+ \\ i.e., call grpc_pollset_kick(pollset, nullptr)
+ \\ (ii) If the cq is of type GRPC_CQ_PLUCK, then search the tag<->worker
+ \\ map on the completion queue to find the worker. Then specifically
+ \\ kick that worker i.e call grpc_pollset_kick(pollset, worker)
+}
+
+```
+
diff --git a/doc/core/grpc-polling-engines.md b/doc/core/grpc-polling-engines.md
new file mode 100644
index 0000000000..f273913b1e
--- /dev/null
+++ b/doc/core/grpc-polling-engines.md
@@ -0,0 +1,154 @@
+# Polling Engines
+
+_Author: Sree Kuchibhotla (@sreecha) - Sep 2018_
+
+
+## Why do we need a 'polling engine' ?
+
+Polling engine component was created for the following reasons:
+
+- gRPC code deals with a bunch of file descriptors on which events like descriptor being readable/writable/error have to be monitored
+- gRPC code knows the actions to perform when such events happen
+ - For example:
+ - `grpc_endpoint` code calls `recvmsg` call when the fd is readable and `sendmsg` call when the fd is writable
+ - ` tcp_client` connect code issues async `connect` and finishes creating the client once the fd is writable (i.e when the `connect` actually finished)
+- gRPC needed some component that can "efficiently" do the above operations __using the threads provided by the applications (i.e., not create any new threads)__. Also by "efficiently" we mean optimized for latency and throughput
+
+
+## Polling Engine Implementations in gRPC
+There are multiple polling engine implementations depending on the OS and the OS version. Fortunately all of them expose the same interface
+
+- Linux:
+
+ - **`epollex`** (default but requires kernel version >= 4.5),
+ - `epoll1` (If `epollex` is not available and glibc version >= 2.9)
+ - `poll` (If kernel does not have epoll support)
+ - `poll-cv` (If explicitly configured)
+- Mac: **`poll`** (default), `poll-cv` (If explicitly configured)
+- Windows: (no name)
+- One-off polling engines:
+ - AppEngine platform: **`poll-cv`** (default)
+ - NodeJS : `libuv` polling engine implementation (requires different compile `#define`s)
+
+## Polling Engine Interface
+
+### Opaque Structures exposed by the polling engine
+The following are the **Opaque** structures exposed by Polling Engine interface (NOTE: Different polling engine implementations have different definitions of these structures)
+
+- **grpc_fd:** Structure representing a file descriptor
+- **grpc_pollset:** A set of one or more grpc_fds that are ‘polled’ for readable/writable/error events. One grpc_fd can be in multiple `grpc_pollset`s
+- **grpc_pollset_worker:** Structure representing a ‘polling thread’ - more specifically, the thread that calls `grpc_pollset_work()` API
+- **grpc_pollset_set:** A group of `grpc_fds`, `grpc_pollsets` and `grpc_pollset_sets` (yes, a `grpc_pollset_set` can contain other `grpc_pollset_sets`)
+
+### Polling engine API
+
+#### grpc_fd
+- **grpc\_fd\_notify\_on\_[read|write|error]**
+ - Signature: `grpc_fd_notify_on_(grpc_fd* fd, grpc_closure* closure)`
+ - Register a [closure](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/iomgr/closure.h#L67) to be called when the fd becomes readable/writable or has an error (In grpc parlance, we refer to this act as “arming the fd”)
+ - The closure is called exactly once per event. I.e once the fd becomes readable (or writable or error), the closure is fired and the fd is ‘unarmed’. To be notified again, the fd has to be armed again.
+
+- **grpc_fd_shutdown**
+ - Signature: `grpc_fd_shutdown(grpc_fd* fd)`
+ - Any current (or future) closures registered for readable/writable/error events are scheduled immediately with an error
+
+- **grpc_fd_orphan**
+ - Signature: `grpc_fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, char* reason)`
+ - Release the `grpc_fd` structure and call `on_done` closure when the operation is complete
+ - If `release_fd` is set to `nullptr`, then `close()` the underlying fd as well. If not, put the underlying fd in `release_fd` (and do not call `close()`)
+ - `release_fd` set to non-null in cases where the underlying fd is NOT owned by grpc core (like for example the fds used by C-Ares DNS resolver )
+
+#### grpc_pollset
+
+- **grpc_pollset_add_fd **
+ - Signature: `grpc_pollset_add_fd(grpc_pollset* ps, grpc_fd *fd)`
+ - Add fd to pollset
+ > **NOTE**: There is no `grpc_pollset_remove_fd`. This is because calling `grpc_fd_orphan()` will effectively remove the fd from all the pollsets it’s a part of
+
+- ** grpc_pollset_work **
+ - Signature: `grpc_pollset_work(grpc_pollset* ps, grpc_pollset_worker** worker, grpc_millis deadline)`
+ > **NOTE**: `grpc_pollset_work()` requires the pollset mutex to be locked before calling it. Shortly after calling `grpc_pollset_work()`, the function populates the `*worker` pointer (among other things) and releases the mutex. Once `grpc_pollset_work()` returns, the `*worker` pointer is **invalid** and should not be used anymore. See the code in `completion_queue.cc` to see how this is used.
+ - Poll the fds in the pollset for events AND return when ANY of the following is true:
+ - Deadline expired
+ - Some fds in the pollset were found to be readable/writable/error and those associated closures were ‘scheduled’ (but not necessarily executed)
+ - worker is “kicked” (see `grpc_pollset_kick` for more details)
+
+- **grpc_pollset_kick**
+ - Signature: `grpc_pollset_kick(grpc_pollset* ps, grpc_pollset_worker* worker)`
+ - “Kick the worker” i.e Force the worker to return from grpc_pollset_work()
+ - If `worker == nullptr`, kick ANY worker active on that pollset
+
+#### grpc_pollset_set
+
+- **grpc\_pollset\_set\_[add|del]\_fd**
+ - Signature: `grpc_pollset_set_[add|del]_fd(grpc_pollset_set* pss, grpc_fd *fd)`
+Add/Remove fd to the `grpc_pollset_set`
+
+- **grpc\_pollset\_set_[add|del]\_pollset**
+ - Signature: `grpc_pollset_set_[add|del]_pollset(grpc_pollset_set* pss, grpc_pollset* ps)`
+ - What does adding a pollset to a pollset_set mean ?
+ - It means that calling `grpc_pollset_work()` on the pollset will also poll all the fds in the pollset_set i.e semantically, it is similar to adding all the fds inside pollset_set to the pollset.
+ - This guarantee is no longer true once the pollset is removed from the pollset_set
+
+- **grpc\_pollset\_set_[add|del]\_pollset\_set**
+ - Signature: `grpc_pollset_set_[add|del]_pollset_set(grpc_pollset_set* bag, grpc_pollset_set* item)`
+ - Semantically, this is similar to adding all the fds in the ‘bag’ pollset_set to the ‘item’ pollset_set
+
+
+#### Recap:
+
+__Relation between grpc_pollset_worker, grpc_pollset and grpc_fd:__
+
+![image](../images/grpc-ps-pss-fd.png)
+
+__grpc_pollset_set__
+
+![image](../images/grpc-pss.png)
+
+
+## Polling Engine Implementations
+
+### epoll1
+
+![image](../images/grpc-epoll1.png)
+
+Code at `src/core/lib/iomgr/ev_epoll1_posix.cc`
+
+- The logic to choose a designated poller is quite complicated. Pollsets are internally sharded into what are called `pollset_neighborhood` (a structure internal to `epoll1` polling engine implementation). `grpc_pollset_workers` that call `grpc_pollset_work` on a given pollset are all queued in a linked-list against the `grpc_pollset`. The head of the linked list is called "root worker"
+
+- There are as many neighborhoods as the number of cores. A pollset is put in a neighborhood based on the CPU core of the root worker thread. When picking the next designated poller, we always try to find another worker on the current pollset. If there are no more workers in the current pollset, a `pollset_neighborhood` listed is scanned to pick the next pollset and worker that could be the new designated poller.
+ - NOTE: There is room to tune this implementation. All we really need is good way to maintain a list of `grpc_pollset_workers` with a way to group them per-pollset (needed to implement `grpc_pollset_kick` semantics) and a way randomly select a new designated poller
+
+- See [`begin_worker()`](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/iomgr/ev_epoll1_linux.cc#L729) function to see how a designated poller is chosen. Similarly [`end_worker()`](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/iomgr/ev_epoll1_linux.cc#L916) function is called by the worker that was just out of `epoll_wait()` and will have to choose a new designated poller)
+
+
+### epollex
+
+![image](../images/grpc-epollex.png)
+
+Code at `src/core/lib/iomgr/ev_epollex_posix.cc`
+
+- FDs are added to multiple epollsets with EPOLLEXCLUSIVE flag. This prevents multiple worker threads from waking up from polling whenever the fd is readable/writable
+
+- A few observations:
+
+ - If multiple pollsets are pointing to the same `Pollable`, then the `pollable` MUST be either empty or of type `PO_FD` (i.e single-fd)
+ - A multi-pollable has one-and-only-one incoming link from a pollset
+ - The same FD can be in multiple `Pollable`s (even if one of the `Pollable`s is of type PO_FD)
+ - There cannot be two `Pollable`s of type PO_FD for the same fd
+
+- Why do we need `Pollable` of type PO_FD and PO_EMTPY ?
+ - The main reason is the Sync client API
+ - We create one new completion queue per call. If we didn’t have PO_EMPTY and PO_FD type pollables, then every call on a given channel will effectively have to create a `Pollable` and hence an epollset. This is because every completion queue automatically creates a pollset and the channel fd will have to be put in that pollset. This clearly requires an epollset to put that fd. Creating an epollset per call (even if we delete the epollset once the call is completed) would mean a lot of sys calls to create/delete epoll fds. This is clearly not a good idea.
+ - With these new types of `Pollable`s, all pollsets (corresponding to the new per-call completion queue) will initially point to PO_EMPTY global epollset. Then once the channel fd is added to the pollset, the pollset will point to the `Pollable` of type PO_FD containing just that fd (i.e it will reuse the existing `Pollable`). This way, the epoll fd creation/deletion churn is avoided.
+
+
+### Other polling engine implementations (poll and windows polling engine)
+- **poll** polling engine: gRPC's `poll` polling engine is quite complicated. It uses the `poll()` function to do the polling (and hence it is for platforms like osx where epoll is not available)
+ - The implementation is further complicated by the fact that poll() is level triggered (just keep this in mind in case you wonder why the code at `src/core/lib/iomgr/ev_poll_posix.cc` is written a certain/seemingly complicated way :))
+
+- **Polling engine on Windows**: Windows polling engine looks nothing like other polling engines
+ - Unlike the grpc polling engines for Unix systems (epollex, epoll1 and poll) Windows endpoint implementation and polling engine implementations are very closely tied together
+ - Windows endpoint read/write API implementations use the Windows IO API which require specifying an [I/O completion port](https://docs.microsoft.com/en-us/windows/desktop/fileio/i-o-completion-ports)
+ - In Windows polling engine’s grpc_pollset_work() implementation, ONE of the threads is chosen to wait on the I/O completion port while other threads wait on a condition variable (much like the turnstile polling in epollex/epoll1)
+
diff --git a/doc/images/grpc-call-channel-cq.png b/doc/images/grpc-call-channel-cq.png
new file mode 100644
index 0000000000..d73b987ee9
--- /dev/null
+++ b/doc/images/grpc-call-channel-cq.png
Binary files differ
diff --git a/doc/images/grpc-client-lb-pss.png b/doc/images/grpc-client-lb-pss.png
new file mode 100644
index 0000000000..188e3654ec
--- /dev/null
+++ b/doc/images/grpc-client-lb-pss.png
Binary files differ
diff --git a/doc/images/grpc-cq.png b/doc/images/grpc-cq.png
new file mode 100644
index 0000000000..2d9e095862
--- /dev/null
+++ b/doc/images/grpc-cq.png
Binary files differ
diff --git a/doc/images/grpc-epoll1.png b/doc/images/grpc-epoll1.png
new file mode 100644
index 0000000000..3ab9a4c7d1
--- /dev/null
+++ b/doc/images/grpc-epoll1.png
Binary files differ
diff --git a/doc/images/grpc-epollex.png b/doc/images/grpc-epollex.png
new file mode 100644
index 0000000000..86dc0005b3
--- /dev/null
+++ b/doc/images/grpc-epollex.png
Binary files differ
diff --git a/doc/images/grpc-ps-pss-fd.png b/doc/images/grpc-ps-pss-fd.png
new file mode 100644
index 0000000000..790af7f1bc
--- /dev/null
+++ b/doc/images/grpc-ps-pss-fd.png
Binary files differ
diff --git a/doc/images/grpc-pss.png b/doc/images/grpc-pss.png
new file mode 100644
index 0000000000..3a0dd9c3ee
--- /dev/null
+++ b/doc/images/grpc-pss.png
Binary files differ
diff --git a/doc/images/grpc-server-cq-fds.png b/doc/images/grpc-server-cq-fds.png
new file mode 100644
index 0000000000..e52bfac81c
--- /dev/null
+++ b/doc/images/grpc-server-cq-fds.png
Binary files differ
diff --git a/examples/python/interceptors/default_value/default_value_client_interceptor.py b/examples/python/interceptors/default_value/default_value_client_interceptor.py
index c549f2b861..c935b95491 100644
--- a/examples/python/interceptors/default_value/default_value_client_interceptor.py
+++ b/examples/python/interceptors/default_value/default_value_client_interceptor.py
@@ -13,8 +13,6 @@
# limitations under the License.
"""Interceptor that adds headers to outgoing requests."""
-import collections
-
import grpc
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index 03ec223279..b51c14eba9 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -190,7 +190,6 @@ Pod::Spec.new do |s|
'src/cpp/client/credentials_cc.cc',
'src/cpp/client/generic_stub.cc',
'src/cpp/common/alarm.cc',
- 'src/cpp/common/callback_common.cc',
'src/cpp/common/channel_arguments.cc',
'src/cpp/common/channel_filter.cc',
'src/cpp/common/completion_queue_cc.cc',
@@ -396,7 +395,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
- 'src/core/lib/iomgr/ev_epollsig_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h',
'src/core/lib/iomgr/exec_ctx.h',
@@ -586,7 +584,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
- 'src/core/lib/iomgr/ev_epollsig_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h',
'src/core/lib/iomgr/exec_ctx.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 5a82a4200a..d575ca666a 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -181,7 +181,7 @@ Pod::Spec.new do |s|
ss.header_mappings_dir = '.'
ss.libraries = 'z'
ss.dependency "#{s.name}/Interface", version
- ss.dependency 'BoringSSL-GRPC', '0.0.1'
+ ss.dependency 'BoringSSL-GRPC', '0.0.2'
ss.dependency 'nanopb', '~> 0.3'
ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS'
@@ -404,7 +404,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
- 'src/core/lib/iomgr/ev_epollsig_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h',
'src/core/lib/iomgr/exec_ctx.h',
@@ -550,7 +549,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
- 'src/core/lib/iomgr/ev_epollsig_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
'src/core/lib/iomgr/ev_posix.cc',
'src/core/lib/iomgr/ev_windows.cc',
@@ -1007,7 +1005,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
- 'src/core/lib/iomgr/ev_epollsig_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h',
'src/core/lib/iomgr/exec_ctx.h',
@@ -1307,5 +1304,6 @@ Pod::Spec.new do |s|
s.prepare_command = <<-END_OF_COMMAND
find src/core/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
find src/core/ -type f -path '*.grpc_back' -print0 | xargs -0 rm
+ find src/core/ -type f \\( -path '*.h' -or -path '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/;#include <openssl_grpc/;g'
END_OF_COMMAND
end
diff --git a/grpc.def b/grpc.def
index b7ba2c5d10..345c0a786c 100644
--- a/grpc.def
+++ b/grpc.def
@@ -77,6 +77,7 @@ EXPORTS
grpc_channelz_get_servers
grpc_channelz_get_channel
grpc_channelz_get_subchannel
+ grpc_channelz_get_socket
grpc_insecure_channel_create_from_fd
grpc_server_add_insecure_channel_from_fd
grpc_use_signal
diff --git a/grpc.gemspec b/grpc.gemspec
index c8e58faec9..81f93f4419 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -340,7 +340,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/error_internal.h )
s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.h )
s.files += %w( src/core/lib/iomgr/ev_epollex_linux.h )
- s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.h )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
s.files += %w( src/core/lib/iomgr/ev_posix.h )
s.files += %w( src/core/lib/iomgr/exec_ctx.h )
@@ -486,7 +485,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/error.cc )
s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.cc )
s.files += %w( src/core/lib/iomgr/ev_epollex_linux.cc )
- s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.cc )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.cc )
s.files += %w( src/core/lib/iomgr/ev_posix.cc )
s.files += %w( src/core/lib/iomgr/ev_windows.cc )
diff --git a/grpc.gyp b/grpc.gyp
index b8aae44de3..16b182349e 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -310,7 +310,6 @@
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
- 'src/core/lib/iomgr/ev_epollsig_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
'src/core/lib/iomgr/ev_posix.cc',
'src/core/lib/iomgr/ev_windows.cc',
@@ -593,16 +592,6 @@
],
},
{
- 'target_name': 'grpc_dll',
- 'type': 'static_library',
- 'dependencies': [
- 'gpr',
- 'grpc',
- ],
- 'sources': [
- ],
- },
- {
'target_name': 'grpc_test_util',
'type': 'static_library',
'dependencies': [
@@ -672,7 +661,6 @@
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
- 'src/core/lib/iomgr/ev_epollsig_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
'src/core/lib/iomgr/ev_posix.cc',
'src/core/lib/iomgr/ev_windows.cc',
@@ -907,7 +895,6 @@
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
- 'src/core/lib/iomgr/ev_epollsig_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
'src/core/lib/iomgr/ev_posix.cc',
'src/core/lib/iomgr/ev_windows.cc',
@@ -1120,7 +1107,6 @@
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
- 'src/core/lib/iomgr/ev_epollsig_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
'src/core/lib/iomgr/ev_posix.cc',
'src/core/lib/iomgr/ev_windows.cc',
@@ -1381,7 +1367,6 @@
'src/cpp/client/credentials_cc.cc',
'src/cpp/client/generic_stub.cc',
'src/cpp/common/alarm.cc',
- 'src/cpp/common/callback_common.cc',
'src/cpp/common/channel_arguments.cc',
'src/cpp/common/channel_filter.cc',
'src/cpp/common/completion_queue_cc.cc',
@@ -1529,7 +1514,6 @@
'src/cpp/client/credentials_cc.cc',
'src/cpp/client/generic_stub.cc',
'src/cpp/common/alarm.cc',
- 'src/cpp/common/callback_common.cc',
'src/cpp/common/channel_arguments.cc',
'src/cpp/common/channel_filter.cc',
'src/cpp/common/completion_queue_cc.cc',
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 3ef95ff462..a9beee1c9e 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -111,7 +111,8 @@ GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_pluck(
of GRPC_CQ_CALLBACK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING.
This function is experimental. */
GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_callback(
- void* shutdown_callback, void* reserved);
+ grpc_experimental_completion_queue_functor* shutdown_callback,
+ void* reserved);
/** Create a completion queue */
GRPCAPI grpc_completion_queue* grpc_completion_queue_create(
@@ -510,6 +511,10 @@ GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id);
is allocated and must be freed by the application. */
GRPCAPI char* grpc_channelz_get_subchannel(intptr_t subchannel_id);
+/* Returns a single Socket, or else a NOT_FOUND code. The returned string
+ is allocated and must be freed by the application. */
+GRPCAPI char* grpc_channelz_get_socket(intptr_t socket_id);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 02d87a493a..de90971cc5 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -532,14 +532,14 @@ typedef struct grpc_alts_credentials_options grpc_alts_credentials_options;
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI grpc_alts_credentials_options*
-grpc_alts_credentials_client_options_create();
+grpc_alts_credentials_client_options_create(void);
/**
* This method creates a grpc ALTS credentials server options instance.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI grpc_alts_credentials_options*
-grpc_alts_credentials_server_options_create();
+grpc_alts_credentials_server_options_create(void);
/**
* This method adds a target service account to grpc client's ALTS credentials
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 5f3b96f40b..9ed5b3c1d4 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -660,6 +660,19 @@ typedef enum {
GRPC_CQ_CALLBACK
} grpc_cq_completion_type;
+/** EXPERIMENTAL: Specifies an interface class to be used as a tag
+ for callback-based completion queues. This can be used directly,
+ as the first element of a struct in C, or as a base class in C++.
+ Its "run" value should be assigned to some non-member function, such as
+ a static method. */
+typedef struct grpc_experimental_completion_queue_functor {
+ /** The run member specifies a function that will be called when this
+ tag is extracted from the completion queue. Its arguments will be a
+ pointer to this functor and a boolean that indicates whether the
+ operation succeeded (non-zero) or failed (zero) */
+ void (*functor_run)(struct grpc_experimental_completion_queue_functor*, int);
+} grpc_experimental_completion_queue_functor;
+
/* The upgrade to version 2 is currently experimental. */
#define GRPC_CQ_CURRENT_VERSION 2
@@ -678,7 +691,7 @@ typedef struct grpc_completion_queue_attributes {
/* EXPERIMENTAL: START OF VERSION 2 CQ ATTRIBUTES */
/** When creating a callbackable CQ, pass in a functor to get invoked when
* shutdown is complete */
- void* cq_shutdown_cb;
+ grpc_experimental_completion_queue_functor* cq_shutdown_cb;
/* END OF VERSION 2 CQ ATTRIBUTES */
} grpc_completion_queue_attributes;
diff --git a/include/grpcpp/impl/codegen/callback_common.h b/include/grpcpp/impl/codegen/callback_common.h
index 8b3ad66a8d..ca2f867d04 100644
--- a/include/grpcpp/impl/codegen/callback_common.h
+++ b/include/grpcpp/impl/codegen/callback_common.h
@@ -21,25 +21,36 @@
#include <functional>
+#include <grpc/impl/codegen/grpc_types.h>
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/channel_interface.h>
#include <grpcpp/impl/codegen/config.h>
#include <grpcpp/impl/codegen/core_codegen_interface.h>
#include <grpcpp/impl/codegen/status.h>
-// Forward declarations
-namespace grpc_core {
-class CQCallbackInterface;
-};
-
namespace grpc {
namespace internal {
+/// An exception-safe way of invoking a user-specified callback function
+template <class Func, class Arg>
+void CatchingCallback(Func&& func, Arg&& arg) {
+#if GRPC_ALLOW_EXCEPTIONS
+ try {
+ func(arg);
+ } catch (...) {
+ // nothing to return or change here, just don't crash the library
+ }
+#else // GRPC_ALLOW_EXCEPTIONS
+ func(arg);
+#endif // GRPC_ALLOW_EXCEPTIONS
+}
+
// The contract on these tags is that they are single-shot. They must be
// constructed and then fired at exactly one point. There is no expectation
// that they can be reused without reconstruction.
-class CallbackWithStatusTag {
+class CallbackWithStatusTag
+ : public grpc_experimental_completion_queue_functor {
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
@@ -54,24 +65,49 @@ class CallbackWithStatusTag {
static void operator delete(void*, void*) { assert(0); }
CallbackWithStatusTag(grpc_call* call, std::function<void(Status)> f,
- CompletionQueueTag* ops);
+ CompletionQueueTag* ops)
+ : call_(call), func_(std::move(f)), ops_(ops) {
+ g_core_codegen_interface->grpc_call_ref(call);
+ functor_run = &CallbackWithStatusTag::StaticRun;
+ }
~CallbackWithStatusTag() {}
- void* tag() { return static_cast<void*>(impl_); }
- Status* status_ptr() { return status_; }
- CompletionQueueTag* ops() { return ops_; }
+ Status* status_ptr() { return &status_; }
// force_run can not be performed on a tag if operations using this tag
// have been sent to PerformOpsOnCall. It is intended for error conditions
// that are detected before the operations are internally processed.
- void force_run(Status s);
+ void force_run(Status s) {
+ status_ = std::move(s);
+ Run(true);
+ }
private:
- grpc_core::CQCallbackInterface* impl_;
- Status* status_;
+ grpc_call* call_;
+ std::function<void(Status)> func_;
CompletionQueueTag* ops_;
+ Status status_;
+
+ static void StaticRun(grpc_experimental_completion_queue_functor* cb,
+ int ok) {
+ static_cast<CallbackWithStatusTag*>(cb)->Run(static_cast<bool>(ok));
+ }
+ void Run(bool ok) {
+ void* ignored = ops_;
+
+ GPR_CODEGEN_ASSERT(ops_->FinalizeResult(&ignored, &ok));
+ GPR_CODEGEN_ASSERT(ignored == ops_);
+
+ // Last use of func_ or status_, so ok to move them out
+ CatchingCallback(std::move(func_), std::move(status_));
+
+ func_ = nullptr; // reset to clear this out for sure
+ status_ = Status(); // reset to clear this out for sure
+ g_core_codegen_interface->grpc_call_unref(call_);
+ }
};
-class CallbackWithSuccessTag {
+class CallbackWithSuccessTag
+ : public grpc_experimental_completion_queue_functor {
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
@@ -86,19 +122,40 @@ class CallbackWithSuccessTag {
static void operator delete(void*, void*) { assert(0); }
CallbackWithSuccessTag(grpc_call* call, std::function<void(bool)> f,
- CompletionQueueTag* ops);
+ CompletionQueueTag* ops)
+ : call_(call), func_(std::move(f)), ops_(ops) {
+ g_core_codegen_interface->grpc_call_ref(call);
+ functor_run = &CallbackWithSuccessTag::StaticRun;
+ }
- void* tag() { return static_cast<void*>(impl_); }
CompletionQueueTag* ops() { return ops_; }
// force_run can not be performed on a tag if operations using this tag
// have been sent to PerformOpsOnCall. It is intended for error conditions
// that are detected before the operations are internally processed.
- void force_run(bool ok);
+ void force_run(bool ok) { Run(ok); }
private:
- grpc_core::CQCallbackInterface* impl_;
+ grpc_call* call_;
+ std::function<void(bool)> func_;
CompletionQueueTag* ops_;
+
+ static void StaticRun(grpc_experimental_completion_queue_functor* cb,
+ int ok) {
+ static_cast<CallbackWithSuccessTag*>(cb)->Run(static_cast<bool>(ok));
+ }
+ void Run(bool ok) {
+ void* ignored = ops_;
+ bool new_ok = ok;
+ GPR_CODEGEN_ASSERT(ops_->FinalizeResult(&ignored, &new_ok));
+ GPR_CODEGEN_ASSERT(ignored == ops_);
+
+ // Last use of func_, so ok to move it out for rvalue call above
+ CatchingCallback(std::move(func_), ok);
+
+ func_ = nullptr; // reset to clear this out for sure
+ g_core_codegen_interface->grpc_call_unref(call_);
+ }
};
} // namespace internal
diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h
index fc81c8aa0a..4d4faea063 100644
--- a/include/grpcpp/impl/codegen/client_callback.h
+++ b/include/grpcpp/impl/codegen/client_callback.h
@@ -84,7 +84,7 @@ class CallbackUnaryCallImpl {
ops->AllowNoMessage();
ops->ClientSendClose();
ops->ClientRecvStatus(context, tag->status_ptr());
- ops->set_cq_tag(tag->tag());
+ ops->set_cq_tag(tag);
call.PerformOps(ops);
}
};
diff --git a/package.xml b/package.xml
index 9c0e078e92..586bab004f 100644
--- a/package.xml
+++ b/package.xml
@@ -345,7 +345,6 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/error_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.h" role="src" />
- <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" />
@@ -491,7 +490,6 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/error.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.cc" role="src" />
- <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_windows.cc" role="src" />
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc
index 1e0c36451b..56716493dc 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -128,6 +128,7 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file,
"");
}
static const char* headers_strs[] = {
+ "functional",
"grpcpp/impl/codegen/async_generic_service.h",
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
@@ -547,6 +548,116 @@ void PrintHeaderClientMethod(grpc_generator::Printer* printer,
}
}
+void PrintHeaderClientMethodCallbackInterfacesStart(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ // This declares the interface for the callback-based API. The components
+ // are pure; even though this is new (post-1.0) API, it can be pure because
+ // it is an entirely new interface that happens to be scoped within
+ // StubInterface, not new additions to StubInterface itself
+ printer->Print("class experimental_async_interface {\n");
+ // All methods in this new interface are public. There is no need for private
+ // "Raw" methods since the callback-based API returns unowned raw pointers
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print("virtual ~experimental_async_interface() {}\n");
+}
+
+void PrintHeaderClientMethodCallbackInterfaces(
+ grpc_generator::Printer* printer, const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars, bool is_public) {
+ // Reserve is_public for future expansion
+ assert(is_public);
+
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "virtual void $Method$(::grpc::ClientContext* context, "
+ "const $Request$* request, $Response$* response, "
+ "std::function<void(::grpc::Status)>) = 0;\n");
+ } else if (ClientOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for client-side streaming
+ } else if (ServerOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for server-side streaming
+ } else if (method->BidiStreaming()) {
+ // TODO(vjpai): Add support for bidi streaming
+ }
+}
+
+void PrintHeaderClientMethodCallbackInterfacesEnd(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ printer->Outdent();
+ printer->Print("};\n");
+
+ // Declare a function to give the async stub contents. It can't be pure
+ // since this is a new API in StubInterface, but it is meaningless by default
+ // (since any stub that wants to use it must have its own implementation of
+ // the callback functions therein), so make the default return value nullptr.
+ // Intentionally include the word "class" to avoid possible shadowing.
+ printer->Print(
+ "virtual class experimental_async_interface* experimental_async() { "
+ "return nullptr; }\n");
+}
+
+void PrintHeaderClientMethodCallbackStart(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ // This declares the stub entry for the callback-based API.
+ printer->Print("class experimental_async final :\n");
+ printer->Print(" public StubInterface::experimental_async_interface {\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+}
+
+void PrintHeaderClientMethodCallback(grpc_generator::Printer* printer,
+ const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars,
+ bool is_public) {
+ // Reserve is_public for future expansion
+ assert(is_public);
+
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "void $Method$(::grpc::ClientContext* context, "
+ "const $Request$* request, $Response$* response, "
+ "std::function<void(::grpc::Status)>) override;\n");
+ } else if (ClientOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for client-side streaming
+ } else if (ServerOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for server-side streaming
+ } else if (method->BidiStreaming()) {
+ // TODO(vjpai): Add support for bidi streaming
+ }
+}
+
+void PrintHeaderClientMethodCallbackEnd(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ printer->Outdent();
+ printer->Print(" private:\n");
+ printer->Indent();
+ printer->Print("friend class Stub;\n");
+ printer->Print("explicit experimental_async(Stub* stub): stub_(stub) { }\n");
+ // include a function with a dummy use of stub_ to avoid an unused
+ // private member warning for service with no methods
+ printer->Print("Stub* stub() { return stub_; }\n");
+ printer->Print("Stub* stub_;\n");
+ printer->Outdent();
+ printer->Print("};\n");
+
+ printer->Print(
+ "class experimental_async_interface* experimental_async() override { "
+ "return &async_stub_; }\n");
+}
+
void PrintHeaderClientMethodData(grpc_generator::Printer* printer,
const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
@@ -951,6 +1062,14 @@ void PrintHeaderService(grpc_generator::Printer* printer,
true);
printer->Print(service->method(i)->GetTrailingComments("//").c_str());
}
+ PrintHeaderClientMethodCallbackInterfacesStart(printer, vars);
+ for (int i = 0; i < service->method_count(); ++i) {
+ printer->Print(service->method(i)->GetLeadingComments("//").c_str());
+ PrintHeaderClientMethodCallbackInterfaces(printer, service->method(i).get(),
+ vars, true);
+ printer->Print(service->method(i)->GetTrailingComments("//").c_str());
+ }
+ PrintHeaderClientMethodCallbackInterfacesEnd(printer, vars);
printer->Outdent();
printer->Print("private:\n");
printer->Indent();
@@ -970,10 +1089,17 @@ void PrintHeaderService(grpc_generator::Printer* printer,
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
}
+ PrintHeaderClientMethodCallbackStart(printer, vars);
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderClientMethodCallback(printer, service->method(i).get(), vars,
+ true);
+ }
+ PrintHeaderClientMethodCallbackEnd(printer, vars);
printer->Outdent();
printer->Print("\n private:\n");
printer->Indent();
printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
+ printer->Print("class experimental_async async_stub_{this};\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
}
@@ -1199,10 +1325,12 @@ grpc::string GetSourceIncludes(grpc_generator::File* file,
std::map<grpc::string, grpc::string> vars;
static const char* headers_strs[] = {
+ "functional",
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/channel_interface.h",
"grpcpp/impl/codegen/client_unary_call.h",
+ "grpcpp/impl/codegen/client_callback.h",
"grpcpp/impl/codegen/method_handler_impl.h",
"grpcpp/impl/codegen/rpc_service_method.h",
"grpcpp/impl/codegen/service_type.h",
@@ -1247,6 +1375,17 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
" return ::grpc::internal::BlockingUnaryCall"
"(channel_.get(), rpcmethod_$Method$_, "
"context, request, response);\n}\n\n");
+
+ printer->Print(*vars,
+ "void $ns$$Service$::Stub::experimental_async::$Method$("
+ "::grpc::ClientContext* context, "
+ "const $Request$* request, $Response$* response, "
+ "std::function<void(::grpc::Status)> f) {\n");
+ printer->Print(*vars,
+ " return ::grpc::internal::CallbackUnaryCall"
+ "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
+ "context, request, response, std::move(f));\n}\n\n");
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1277,6 +1416,9 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
"rpcmethod_$Method$_, "
"context, response);\n"
"}\n\n");
+
+ // TODO(vjpai): Add callback version
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1308,6 +1450,9 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
+
+ // TODO(vjpai): Add callback version
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1339,6 +1484,9 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
"rpcmethod_$Method$_, "
"context);\n"
"}\n\n");
+
+ // TODO(vjpai): Add callback version
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc
index 7e8f59bcd3..b66c920b90 100644
--- a/src/core/ext/filters/client_channel/client_channel_channelz.cc
+++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc
@@ -166,6 +166,17 @@ grpc_json* SubchannelNode::RenderJson() {
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
+ json = top_level_json;
+ // populate the child socket.
+ intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_);
+ if (socket_uuid != 0) {
+ grpc_json* array_parent = grpc_json_create_child(
+ nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
+ json_iterator = grpc_json_create_child(json_iterator, array_parent, nullptr,
+ nullptr, GRPC_JSON_OBJECT, false);
+ grpc_json_add_number_string_child(json_iterator, nullptr, "socketId",
+ socket_uuid);
+ }
return top_level_json;
}
diff --git a/src/core/ext/filters/client_channel/connector.h b/src/core/ext/filters/client_channel/connector.h
index 556594929c..ea34dcdab5 100644
--- a/src/core/ext/filters/client_channel/connector.h
+++ b/src/core/ext/filters/client_channel/connector.h
@@ -47,6 +47,9 @@ typedef struct {
/** channel arguments (to be passed to the filters) */
grpc_channel_args* channel_args;
+
+ /** socket uuid of the connected transport. 0 if not available */
+ intptr_t socket_uuid;
} grpc_connect_out_args;
struct grpc_connector_vtable {
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index 1ee1925a25..0061190016 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -852,10 +852,12 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
}
} else {
// No valid initial response or serverlist found.
+ char* response_slice_str =
+ grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX);
gpr_log(GPR_ERROR,
"[grpclb %p] Invalid LB response received: '%s'. Ignoring.",
- grpclb_policy,
- grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
+ grpclb_policy, response_slice_str);
+ gpr_free(response_slice_str);
}
grpc_slice_unref_internal(response_slice);
if (!grpclb_policy->shutting_down_) {
diff --git a/src/core/ext/filters/client_channel/lb_policy_factory.h b/src/core/ext/filters/client_channel/lb_policy_factory.h
index c07792d8a7..62bdbf2689 100644
--- a/src/core/ext/filters/client_channel/lb_policy_factory.h
+++ b/src/core/ext/filters/client_channel/lb_policy_factory.h
@@ -70,16 +70,14 @@ grpc_lb_addresses* grpc_lb_addresses_create(
grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses);
/** Sets the value of the address at index \a index of \a addresses.
- * \a address is a socket address of length \a address_len.
- * Takes ownership of \a balancer_name. */
+ * \a address is a socket address of length \a address_len. */
void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
const void* address, size_t address_len,
bool is_balancer, const char* balancer_name,
void* user_data);
/** Sets the value of the address at index \a index of \a addresses from \a uri.
- * Returns true upon success, false otherwise. Takes ownership of \a
- * balancer_name. */
+ * Returns true upon success, false otherwise. */
bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses,
size_t index, const grpc_uri* uri,
bool is_balancer,
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index 57d0b3759f..2847f4bdc1 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -411,6 +411,14 @@ grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
return subchannel->channelz_subchannel.get();
}
+intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel) {
+ if (subchannel->connected_subchannel != nullptr) {
+ return subchannel->connected_subchannel->socket_uuid();
+ } else {
+ return 0;
+ }
+}
+
static void continue_connect_locked(grpc_subchannel* c) {
grpc_connect_in_args args;
args.interested_parties = c->pollset_set;
@@ -621,6 +629,7 @@ static bool publish_transport_locked(grpc_subchannel* c) {
GRPC_ERROR_UNREF(error);
return false;
}
+ intptr_t socket_uuid = c->connecting_result.socket_uuid;
memset(&c->connecting_result, 0, sizeof(c->connecting_result));
/* initialize state watcher */
@@ -641,7 +650,7 @@ static bool publish_transport_locked(grpc_subchannel* c) {
/* publish */
c->connected_subchannel.reset(grpc_core::New<grpc_core::ConnectedSubchannel>(
- stk, c->channelz_subchannel.get()));
+ stk, c->channelz_subchannel.get(), socket_uuid));
gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
c->connected_subchannel.get(), c);
@@ -811,10 +820,11 @@ namespace grpc_core {
ConnectedSubchannel::ConnectedSubchannel(
grpc_channel_stack* channel_stack,
- channelz::SubchannelNode* channelz_subchannel)
+ channelz::SubchannelNode* channelz_subchannel, intptr_t socket_uuid)
: RefCountedWithTracing<ConnectedSubchannel>(&grpc_trace_stream_refcount),
channel_stack_(channel_stack),
- channelz_subchannel_(channelz_subchannel) {}
+ channelz_subchannel_(channelz_subchannel),
+ socket_uuid_(socket_uuid) {}
ConnectedSubchannel::~ConnectedSubchannel() {
GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index 84febb5204..699f93a8e7 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -86,7 +86,8 @@ class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
};
explicit ConnectedSubchannel(grpc_channel_stack* channel_stack,
- channelz::SubchannelNode* channelz_subchannel);
+ channelz::SubchannelNode* channelz_subchannel,
+ intptr_t socket_uuid);
~ConnectedSubchannel();
grpc_channel_stack* channel_stack() { return channel_stack_; }
@@ -98,12 +99,15 @@ class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
channelz::SubchannelNode* channelz_subchannel() {
return channelz_subchannel_;
}
+ intptr_t socket_uuid() { return socket_uuid_; }
private:
grpc_channel_stack* channel_stack_;
// backpointer to the channelz node in this connected subchannel's
// owning subchannel.
channelz::SubchannelNode* channelz_subchannel_;
+ // uuid of this subchannel's socket. 0 if this subchannel is not connected.
+ const intptr_t socket_uuid_;
};
} // namespace grpc_core
@@ -126,6 +130,8 @@ void grpc_subchannel_call_unref(
grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
grpc_subchannel* subchannel);
+intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel);
+
/** Returns a pointer to the parent data associated with \a subchannel_call.
The data will be of the size specified in \a parent_data_size
field of the args passed to \a grpc_connected_subchannel_create_call(). */
diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc
index 91fa163fec..cd459e47cd 100644
--- a/src/core/ext/filters/http/client/http_client_filter.cc
+++ b/src/core/ext/filters/http/client/http_client_filter.cc
@@ -58,6 +58,8 @@ struct call_data {
grpc_metadata_batch* recv_trailing_metadata;
grpc_closure* original_recv_trailing_metadata_ready;
grpc_closure recv_trailing_metadata_ready;
+ grpc_error* recv_trailing_metadata_error;
+ bool seen_recv_trailing_metadata_ready;
// State for handling send_message ops.
grpc_transport_stream_op_batch* send_message_batch;
size_t send_message_bytes_read;
@@ -157,12 +159,27 @@ static void recv_initial_metadata_ready(void* user_data, grpc_error* error) {
} else {
GRPC_ERROR_REF(error);
}
- GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, error);
+ grpc_closure* closure = calld->original_recv_initial_metadata_ready;
+ calld->original_recv_initial_metadata_ready = nullptr;
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(
+ calld->call_combiner, &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error, "continue recv_trailing_metadata");
+ }
+ GRPC_CLOSURE_RUN(closure, error);
}
static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
+ if (calld->original_recv_initial_metadata_ready != nullptr) {
+ calld->recv_trailing_metadata_error = GRPC_ERROR_REF(error);
+ calld->seen_recv_trailing_metadata_ready = true;
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "deferring recv_trailing_metadata_ready until "
+ "after recv_initial_metadata_ready");
+ return;
+ }
if (error == GRPC_ERROR_NONE) {
error =
client_filter_incoming_metadata(elem, calld->recv_trailing_metadata);
diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc
index 1b3426b120..436ea09d94 100644
--- a/src/core/ext/filters/http/server/http_server_filter.cc
+++ b/src/core/ext/filters/http/server/http_server_filter.cc
@@ -63,8 +63,11 @@ struct call_data {
grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message;
bool seen_recv_message_ready;
+ // State for intercepting recv_trailing_metadata
grpc_closure recv_trailing_metadata_ready;
grpc_closure* original_recv_trailing_metadata_ready;
+ grpc_error* recv_trailing_metadata_ready_error;
+ bool seen_recv_trailing_metadata_ready;
};
struct channel_data {
@@ -301,6 +304,13 @@ static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err) {
} else {
GRPC_ERROR_REF(err);
}
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_ready_error,
+ "resuming hs_recv_trailing_metadata_ready from "
+ "hs_recv_initial_metadata_ready");
+ }
GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, err);
}
@@ -331,6 +341,14 @@ static void hs_recv_message_ready(void* user_data, grpc_error* err) {
static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
+ if (!calld->seen_recv_initial_metadata_ready) {
+ calld->recv_trailing_metadata_ready_error = GRPC_ERROR_REF(err);
+ calld->seen_recv_trailing_metadata_ready = true;
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "deferring hs_recv_trailing_metadata_ready until "
+ "ater hs_recv_initial_metadata_ready");
+ return;
+ }
err = grpc_error_add_child(
GRPC_ERROR_REF(err),
GRPC_ERROR_REF(calld->recv_initial_metadata_ready_error));
diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc
index c17df86f3d..2d3b16d992 100644
--- a/src/core/ext/filters/message_size/message_size_filter.cc
+++ b/src/core/ext/filters/message_size/message_size_filter.cc
@@ -108,6 +108,8 @@ struct call_data {
grpc_closure* next_recv_message_ready;
// Original recv_trailing_metadata callback, invoked after our own.
grpc_closure* original_recv_trailing_metadata_ready;
+ bool seen_recv_trailing_metadata;
+ grpc_error* recv_trailing_metadata_error;
};
struct channel_data {
@@ -147,7 +149,21 @@ static void recv_message_ready(void* user_data, grpc_error* error) {
GRPC_ERROR_REF(error);
}
// Invoke the next callback.
- GRPC_CLOSURE_RUN(calld->next_recv_message_ready, error);
+ grpc_closure* closure = calld->next_recv_message_ready;
+ calld->next_recv_message_ready = nullptr;
+ if (calld->seen_recv_trailing_metadata) {
+ /* We might potentially see another RECV_MESSAGE op. In that case, we do not
+ * want to run the recv_trailing_metadata_ready closure again. The newer
+ * RECV_MESSAGE op cannot cause any errors since the transport has already
+ * invoked the recv_trailing_metadata_ready closure and all further
+ * RECV_MESSAGE ops will get null payloads. */
+ calld->seen_recv_trailing_metadata = false;
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error,
+ "continue recv_trailing_metadata_ready");
+ }
+ GRPC_CLOSURE_RUN(closure, error);
}
// Callback invoked on completion of recv_trailing_metadata
@@ -155,6 +171,14 @@ static void recv_message_ready(void* user_data, grpc_error* error) {
static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
+ if (calld->next_recv_message_ready != nullptr) {
+ calld->seen_recv_trailing_metadata = true;
+ calld->recv_trailing_metadata_error = GRPC_ERROR_REF(error);
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "deferring recv_trailing_metadata_ready until "
+ "after recv_message_ready");
+ return;
+ }
error =
grpc_error_add_child(GRPC_ERROR_REF(error), GRPC_ERROR_REF(calld->error));
// Invoke the next callback.
diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc
index e7522ffba8..0ac84032fd 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc
@@ -117,6 +117,8 @@ static void on_handshake_done(void* arg, grpc_error* error) {
c->args.interested_parties);
c->result->transport =
grpc_create_chttp2_transport(args->args, args->endpoint, true);
+ c->result->socket_uuid =
+ grpc_chttp2_transport_get_socket_uuid(c->result->transport);
GPR_ASSERT(c->result->transport);
// TODO(roth): We ideally want to wait until we receive HTTP/2
// settings from the server before we consider the connection
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 26cad2cc9a..776c15138b 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -157,6 +157,10 @@ bool g_flow_control_enabled = true;
static void destruct_transport(grpc_chttp2_transport* t) {
size_t i;
+ if (t->channelz_socket != nullptr) {
+ t->channelz_socket.reset();
+ }
+
grpc_endpoint_destroy(t->ep);
grpc_slice_buffer_destroy_internal(&t->qbuf);
@@ -335,6 +339,10 @@ static bool read_channel_args(grpc_chttp2_transport* t,
GRPC_ARG_OPTIMIZATION_TARGET,
channel_args->args[i].value.string);
}
+ } else if (0 ==
+ strcmp(channel_args->args[i].key, GRPC_ARG_ENABLE_CHANNELZ)) {
+ t->channelz_socket =
+ grpc_core::MakeRefCounted<grpc_core::channelz::SocketNode>();
} else {
static const struct {
const char* channel_arg_name;
@@ -720,6 +728,14 @@ static void destroy_stream_locked(void* sp, grpc_error* error) {
grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(sp);
grpc_chttp2_transport* t = s->t;
+ if (t->channelz_socket != nullptr) {
+ if ((t->is_client && s->eos_received) || (!t->is_client && s->eos_sent)) {
+ t->channelz_socket->RecordStreamSucceeded();
+ } else {
+ t->channelz_socket->RecordStreamFailed();
+ }
+ }
+
GPR_ASSERT((s->write_closed && s->read_closed) || s->id == 0);
if (s->id != 0) {
GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, s->id) == nullptr);
@@ -1407,6 +1423,9 @@ static void perform_stream_op_locked(void* stream_op,
}
if (op->send_initial_metadata) {
+ if (t->is_client && t->channelz_socket != nullptr) {
+ t->channelz_socket->RecordStreamStartedFromLocal();
+ }
GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA();
GPR_ASSERT(s->send_initial_metadata_finished == nullptr);
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
@@ -1492,6 +1511,7 @@ static void perform_stream_op_locked(void* stream_op,
if (op->send_message) {
GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE();
+ t->num_messages_in_next_write++;
GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE(
op->payload->send_message.send_message->length());
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
@@ -2707,6 +2727,9 @@ static void start_keepalive_ping_locked(void* arg, grpc_error* error) {
if (error != GRPC_ERROR_NONE) {
return;
}
+ if (t->channelz_socket != nullptr) {
+ t->channelz_socket->RecordKeepaliveSent();
+ }
GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
grpc_timer_init(&t->keepalive_watchdog_timer,
grpc_core::ExecCtx::Get()->Now() + t->keepalive_timeout,
@@ -3147,6 +3170,16 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
static const grpc_transport_vtable* get_vtable(void) { return &vtable; }
+intptr_t grpc_chttp2_transport_get_socket_uuid(grpc_transport* transport) {
+ grpc_chttp2_transport* t =
+ reinterpret_cast<grpc_chttp2_transport*>(transport);
+ if (t->channelz_socket != nullptr) {
+ return t->channelz_socket->uuid();
+ } else {
+ return 0;
+ }
+}
+
grpc_transport* grpc_create_chttp2_transport(
const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h
index 9d55b3f4b0..e5872fee43 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.h
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.h
@@ -34,6 +34,8 @@ extern bool g_flow_control_enabled;
grpc_transport* grpc_create_chttp2_transport(
const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client);
+intptr_t grpc_chttp2_transport_get_socket_uuid(grpc_transport* transport);
+
/// Takes ownership of \a read_buffer, which (if non-NULL) contains
/// leftover bytes previously read from the endpoint (e.g., by handshakers).
/// If non-null, \a notify_on_receive_settings will be scheduled when
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.cc b/src/core/ext/transport/chttp2/transport/frame_data.cc
index f8f06f6789..933b32c03c 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.cc
+++ b/src/core/ext/transport/chttp2/transport/frame_data.cc
@@ -62,6 +62,7 @@ grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser,
if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
s->received_last_frame = true;
+ s->eos_received = true;
} else {
s->received_last_frame = false;
}
@@ -191,6 +192,9 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
GPR_ASSERT(stream_out != nullptr);
GPR_ASSERT(p->parsing_frame == nullptr);
p->frame_size |= (static_cast<uint32_t>(*cur));
+ if (t->channelz_socket != nullptr) {
+ t->channelz_socket->RecordMessageReceived();
+ }
p->state = GRPC_CHTTP2_DATA_FRAME;
++cur;
message_flags = 0;
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index 6b5309bab4..ff26dd9255 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -36,6 +36,7 @@
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
+#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/compression/stream_compression.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/iomgr/combiner.h"
@@ -471,6 +472,9 @@ struct grpc_chttp2_transport {
bool keepalive_permit_without_calls;
/** keep-alive state machine state */
grpc_chttp2_keepalive_state keepalive_state;
+
+ grpc_core::RefCountedPtr<grpc_core::channelz::SocketNode> channelz_socket;
+ uint32_t num_messages_in_next_write;
};
typedef enum {
@@ -534,6 +538,10 @@ struct grpc_chttp2_stream {
/** Has trailing metadata been received. */
bool received_trailing_metadata;
+ /* have we sent or received the EOS bit? */
+ bool eos_received;
+ bool eos_sent;
+
/** the error that resulted in this stream being read-closed */
grpc_error* read_closed_error;
/** the error that resulted in this stream being write-closed */
diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc
index 1e491d2ef8..f532b084c9 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.cc
+++ b/src/core/ext/transport/chttp2/transport/parsing.cc
@@ -409,67 +409,81 @@ static void on_initial_header(void* tp, grpc_mdelem md) {
gpr_free(value);
}
- if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
- !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
- /* TODO(ctiller): check for a status like " 0" */
- s->seen_error = true;
- }
+ if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
+ // We don't use grpc_mdelem_eq here to avoid executing additional
+ // instructions. The reasoning is if the payload is not equal, we already
+ // know that the metadata elements are not equal because the md is
+ // confirmed to be static. If we had used grpc_mdelem_eq here, then if the
+ // payloads are not equal, grpc_mdelem_eq executes more instructions to
+ // determine if they're equal or not.
+ if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload ||
+ md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) {
+ s->seen_error = true;
+ }
+ } else {
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+ !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
+ /* TODO(ctiller): check for a status like " 0" */
+ s->seen_error = true;
+ }
- if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
- grpc_millis* cached_timeout =
- static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
- grpc_millis timeout;
- if (cached_timeout != nullptr) {
- timeout = *cached_timeout;
- } else {
- if (GPR_UNLIKELY(
- !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
- char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
- gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
- gpr_free(val);
- timeout = GRPC_MILLIS_INF_FUTURE;
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
+ grpc_millis* cached_timeout = static_cast<grpc_millis*>(
+ grpc_mdelem_get_user_data(md, free_timeout));
+ grpc_millis timeout;
+ if (cached_timeout != nullptr) {
+ timeout = *cached_timeout;
+ } else {
+ if (GPR_UNLIKELY(
+ !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
+ char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+ gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
+ gpr_free(val);
+ timeout = GRPC_MILLIS_INF_FUTURE;
+ }
+ if (GRPC_MDELEM_IS_INTERNED(md)) {
+ /* store the result */
+ cached_timeout =
+ static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
+ *cached_timeout = timeout;
+ grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+ }
}
- if (GRPC_MDELEM_IS_INTERNED(md)) {
- /* store the result */
- cached_timeout =
- static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
- *cached_timeout = timeout;
- grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+ if (timeout != GRPC_MILLIS_INF_FUTURE) {
+ grpc_chttp2_incoming_metadata_buffer_set_deadline(
+ &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
}
+ GRPC_MDELEM_UNREF(md);
+ return;
}
- if (timeout != GRPC_MILLIS_INF_FUTURE) {
- grpc_chttp2_incoming_metadata_buffer_set_deadline(
- &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
- }
+ }
+
+ const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
+ const size_t metadata_size_limit =
+ t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
+ if (new_size > metadata_size_limit) {
+ gpr_log(GPR_DEBUG,
+ "received initial metadata size exceeds limit (%" PRIuPTR
+ " vs. %" PRIuPTR ")",
+ new_size, metadata_size_limit);
+ grpc_chttp2_cancel_stream(
+ t, s,
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "received initial metadata size exceeds limit"),
+ GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_RESOURCE_EXHAUSTED));
+ grpc_chttp2_parsing_become_skip_parser(t);
+ s->seen_error = true;
GRPC_MDELEM_UNREF(md);
} else {
- const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
- const size_t metadata_size_limit =
- t->settings[GRPC_ACKED_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
- if (new_size > metadata_size_limit) {
- gpr_log(GPR_DEBUG,
- "received initial metadata size exceeds limit (%" PRIuPTR
- " vs. %" PRIuPTR ")",
- new_size, metadata_size_limit);
- grpc_chttp2_cancel_stream(
- t, s,
- grpc_error_set_int(
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "received initial metadata size exceeds limit"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
+ grpc_error* error =
+ grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
+ if (error != GRPC_ERROR_NONE) {
+ grpc_chttp2_cancel_stream(t, s, error);
grpc_chttp2_parsing_become_skip_parser(t);
s->seen_error = true;
GRPC_MDELEM_UNREF(md);
- } else {
- grpc_error* error =
- grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
- if (error != GRPC_ERROR_NONE) {
- grpc_chttp2_cancel_stream(t, s, error);
- grpc_chttp2_parsing_become_skip_parser(t);
- s->seen_error = true;
- GRPC_MDELEM_UNREF(md);
- }
}
}
}
@@ -491,8 +505,19 @@ static void on_trailing_header(void* tp, grpc_mdelem md) {
gpr_free(value);
}
- if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
- !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
+ if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
+ // We don't use grpc_mdelem_eq here to avoid executing additional
+ // instructions. The reasoning is if the payload is not equal, we already
+ // know that the metadata elements are not equal because the md is
+ // confirmed to be static. If we had used grpc_mdelem_eq here, then if the
+ // payloads are not equal, grpc_mdelem_eq executes more instructions to
+ // determine if they're equal or not.
+ if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload ||
+ md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) {
+ s->seen_error = true;
+ }
+ } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+ !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
/* TODO(ctiller): check for a status like " 0" */
s->seen_error = true;
}
@@ -598,6 +623,9 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
return init_skip_frame_parser(t, 1);
}
+ if (t->channelz_socket != nullptr) {
+ t->channelz_socket->RecordStreamStartedFromRemote();
+ }
} else {
t->incoming_stream = s;
}
@@ -611,6 +639,9 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
}
t->parser = grpc_chttp2_header_parser_parse;
t->parser_data = &t->hpack_parser;
+ if (t->header_eof) {
+ s->eos_received = true;
+ }
switch (s->header_frames_received) {
case 0:
if (t->is_client && t->header_eof) {
diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc
index 8b73b01dea..d533989444 100644
--- a/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/src/core/ext/transport/chttp2/transport/writing.cc
@@ -569,6 +569,7 @@ class StreamWriteContext {
void SentLastFrame() {
s_->send_trailing_metadata = nullptr;
s_->sent_trailing_metadata = true;
+ s_->eos_sent = true;
if (!t_->is_client && !s_->read_closed) {
grpc_slice_buffer_add(
@@ -632,6 +633,11 @@ void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error* error) {
GPR_TIMER_SCOPE("grpc_chttp2_end_write", 0);
grpc_chttp2_stream* s;
+ if (t->channelz_socket != nullptr) {
+ t->channelz_socket->RecordMessagesSent(t->num_messages_in_next_write);
+ }
+ t->num_messages_in_next_write = 0;
+
while (grpc_chttp2_list_pop_writing_stream(t, &s)) {
if (s->sending_bytes != 0) {
update_list(t, s, static_cast<int64_t>(s->sending_bytes),
diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc
index 375cf25cc6..339c827525 100644
--- a/src/core/lib/channel/channelz.cc
+++ b/src/core/lib/channel/channelz.cc
@@ -62,7 +62,7 @@ CallCountingHelper::CallCountingHelper() {
CallCountingHelper::~CallCountingHelper() {}
void CallCountingHelper::RecordCallStarted() {
- gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1);
+ gpr_atm_no_barrier_fetch_add(&calls_started_, static_cast<gpr_atm>(1));
gpr_atm_no_barrier_store(&last_call_started_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
@@ -81,11 +81,13 @@ void CallCountingHelper::PopulateCallCounts(grpc_json* json) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "callsFailed", calls_failed_);
}
- gpr_timespec ts =
- grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
- json_iterator =
- grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
- gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ if (calls_started_ != 0) {
+ gpr_timespec ts =
+ grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
+ gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ }
}
ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
@@ -180,7 +182,103 @@ grpc_json* ServerNode::RenderJson() {
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
+ return top_level_json;
+}
+
+SocketNode::SocketNode() : BaseNode(EntityType::kSocket) {}
+
+void SocketNode::RecordStreamStartedFromLocal() {
+ gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast<gpr_atm>(1));
+ gpr_atm_no_barrier_store(&last_local_stream_created_millis_,
+ (gpr_atm)ExecCtx::Get()->Now());
+}
+
+void SocketNode::RecordStreamStartedFromRemote() {
+ gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast<gpr_atm>(1));
+ gpr_atm_no_barrier_store(&last_remote_stream_created_millis_,
+ (gpr_atm)ExecCtx::Get()->Now());
+}
+
+void SocketNode::RecordMessagesSent(uint32_t num_sent) {
+ gpr_atm_no_barrier_fetch_add(&messages_sent_, static_cast<gpr_atm>(num_sent));
+ gpr_atm_no_barrier_store(&last_message_sent_millis_,
+ (gpr_atm)ExecCtx::Get()->Now());
+}
+
+void SocketNode::RecordMessageReceived() {
+ gpr_atm_no_barrier_fetch_add(&messages_received_, static_cast<gpr_atm>(1));
+ gpr_atm_no_barrier_store(&last_message_received_millis_,
+ (gpr_atm)ExecCtx::Get()->Now());
+}
+
+grpc_json* SocketNode::RenderJson() {
+ // We need to track these three json objects to build our object
+ grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
+ grpc_json* json = top_level_json;
+ grpc_json* json_iterator = nullptr;
+ // create and fill the ref child
+ json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
+ GRPC_JSON_OBJECT, false);
+ json = json_iterator;
+ json_iterator = nullptr;
+ json_iterator = grpc_json_add_number_string_child(json, json_iterator,
+ "socketId", uuid());
+ // reset json iterators to top level object
json = top_level_json;
+ json_iterator = nullptr;
+ // create and fill the data child.
+ grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
+ GRPC_JSON_OBJECT, false);
+ json = data;
+ json_iterator = nullptr;
+ gpr_timespec ts;
+ if (streams_started_ != 0) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "streamsStarted", streams_started_);
+ if (last_local_stream_created_millis_ != 0) {
+ ts = grpc_millis_to_timespec(last_local_stream_created_millis_,
+ GPR_CLOCK_REALTIME);
+ json_iterator = grpc_json_create_child(
+ json_iterator, json, "lastLocalStreamCreatedTimestamp",
+ gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ }
+ if (last_remote_stream_created_millis_ != 0) {
+ ts = grpc_millis_to_timespec(last_remote_stream_created_millis_,
+ GPR_CLOCK_REALTIME);
+ json_iterator = grpc_json_create_child(
+ json_iterator, json, "lastRemoteStreamCreatedTimestamp",
+ gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ }
+ }
+ if (streams_succeeded_ != 0) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "streamsSucceeded", streams_succeeded_);
+ }
+ if (streams_failed_) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "streamsFailed", streams_failed_);
+ }
+ if (messages_sent_ != 0) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "messagesSent", messages_sent_);
+ ts = grpc_millis_to_timespec(last_message_sent_millis_, GPR_CLOCK_REALTIME);
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "lastMessageSentTimestamp",
+ gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ }
+ if (messages_received_ != 0) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "messagesReceived", messages_received_);
+ ts = grpc_millis_to_timespec(last_message_received_millis_,
+ GPR_CLOCK_REALTIME);
+ json_iterator = grpc_json_create_child(
+ json_iterator, json, "lastMessageReceivedTimestamp",
+ gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ }
+ if (keepalives_sent_ != 0) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "keepAlivesSent", keepalives_sent_);
+ }
return top_level_json;
}
diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h
index 9be256147b..b7ae101238 100644
--- a/src/core/lib/channel/channelz.h
+++ b/src/core/lib/channel/channelz.h
@@ -92,10 +92,10 @@ class CallCountingHelper {
void RecordCallStarted();
void RecordCallFailed() {
- gpr_atm_no_barrier_fetch_add(&calls_failed_, (gpr_atm(1)));
+ gpr_atm_no_barrier_fetch_add(&calls_failed_, static_cast<gpr_atm>(1));
}
void RecordCallSucceeded() {
- gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1)));
+ gpr_atm_no_barrier_fetch_add(&calls_succeeded_, static_cast<gpr_atm>(1));
}
// Common rendering of the call count data and last_call_started_timestamp.
@@ -197,11 +197,39 @@ class ServerNode : public BaseNode {
};
// Handles channelz bookkeeping for sockets
-// TODO(ncteisen): implement in subsequent PR.
class SocketNode : public BaseNode {
public:
- SocketNode() : BaseNode(EntityType::kSocket) {}
+ SocketNode();
~SocketNode() override {}
+
+ grpc_json* RenderJson() override;
+
+ void RecordStreamStartedFromLocal();
+ void RecordStreamStartedFromRemote();
+ void RecordStreamSucceeded() {
+ gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast<gpr_atm>(1));
+ }
+ void RecordStreamFailed() {
+ gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast<gpr_atm>(1));
+ }
+ void RecordMessagesSent(uint32_t num_sent);
+ void RecordMessageReceived();
+ void RecordKeepaliveSent() {
+ gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast<gpr_atm>(1));
+ }
+
+ private:
+ gpr_atm streams_started_ = 0;
+ gpr_atm streams_succeeded_ = 0;
+ gpr_atm streams_failed_ = 0;
+ gpr_atm messages_sent_ = 0;
+ gpr_atm messages_received_ = 0;
+ gpr_atm keepalives_sent_ = 0;
+ gpr_atm last_local_stream_created_millis_ = 0;
+ gpr_atm last_remote_stream_created_millis_ = 0;
+ gpr_atm last_message_sent_millis_ = 0;
+ gpr_atm last_message_received_millis_ = 0;
+ UniquePtr<char> peer_string_;
};
// Creation functions
diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc
index adc7b6ba44..841f1c6104 100644
--- a/src/core/lib/channel/channelz_registry.cc
+++ b/src/core/lib/channel/channelz_registry.cc
@@ -197,3 +197,21 @@ char* grpc_channelz_get_subchannel(intptr_t subchannel_id) {
grpc_json_destroy(top_level_json);
return json_str;
}
+
+char* grpc_channelz_get_socket(intptr_t socket_id) {
+ grpc_core::channelz::BaseNode* socket_node =
+ grpc_core::channelz::ChannelzRegistry::Get(socket_id);
+ if (socket_node == nullptr ||
+ socket_node->type() !=
+ grpc_core::channelz::BaseNode::EntityType::kSocket) {
+ return nullptr;
+ }
+ grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
+ grpc_json* json = top_level_json;
+ grpc_json* socket_json = socket_node->RenderJson();
+ socket_json->key = "socket";
+ grpc_json_link_child(json, socket_json, nullptr);
+ char* json_str = grpc_json_dump_to_string(top_level_json, 0);
+ grpc_json_destroy(top_level_json);
+ return json_str;
+}
diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc
index 13bc69ffb6..146a539027 100644
--- a/src/core/lib/iomgr/error.cc
+++ b/src/core/lib/iomgr/error.cc
@@ -454,7 +454,7 @@ typedef struct {
grpc_status_code code;
const char* msg;
} special_error_status_map;
-static special_error_status_map error_status_map[] = {
+static const special_error_status_map error_status_map[] = {
{GRPC_ERROR_NONE, GRPC_STATUS_OK, ""},
{GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"},
{GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
@@ -463,15 +463,13 @@ static special_error_status_map error_status_map[] = {
bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) {
GPR_TIMER_SCOPE("grpc_error_get_int", 0);
if (grpc_error_is_special(err)) {
- if (which == GRPC_ERROR_INT_GRPC_STATUS) {
- for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
- if (error_status_map[i].error == err) {
- if (p != nullptr) *p = error_status_map[i].code;
- return true;
- }
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
+ if (error_status_map[i].error == err) {
+ if (which != GRPC_ERROR_INT_GRPC_STATUS) return false;
+ if (p != nullptr) *p = error_status_map[i].code;
+ return true;
}
}
- return false;
}
uint8_t slot = err->ints[which];
if (slot != UINT8_MAX) {
@@ -492,15 +490,13 @@ grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which,
bool grpc_error_get_str(grpc_error* err, grpc_error_strs which,
grpc_slice* str) {
if (grpc_error_is_special(err)) {
- if (which == GRPC_ERROR_STR_GRPC_MESSAGE) {
- for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
- if (error_status_map[i].error == err) {
- *str = grpc_slice_from_static_string(error_status_map[i].msg);
- return true;
- }
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
+ if (error_status_map[i].error == err) {
+ if (which != GRPC_ERROR_STR_GRPC_MESSAGE) return false;
+ *str = grpc_slice_from_static_string(error_status_map[i].msg);
+ return true;
}
}
- return false;
}
uint8_t slot = err->strs[which];
if (slot != UINT8_MAX) {
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc
index aa5016bd8f..6ef889b0fe 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.cc
+++ b/src/core/lib/iomgr/ev_epoll1_linux.cc
@@ -273,6 +273,10 @@ static gpr_mu fork_fd_list_mu;
static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
static void fd_global_shutdown(void) {
+ // TODO(guantaol): We don't have a reasonable explanation about this
+ // lock()/unlock() pattern. It can be a valid barrier if there is at most one
+ // pending lock() at this point. Otherwise, there is still a possibility of
+ // use-after-free race. Need to reason about the code and/or clean it up.
gpr_mu_lock(&fd_freelist_mu);
gpr_mu_unlock(&fd_freelist_mu);
while (fd_freelist != nullptr) {
diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc
index b082634af1..06a382c556 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.cc
+++ b/src/core/lib/iomgr/ev_epollex_linux.cc
@@ -403,6 +403,10 @@ static void unref_by(grpc_fd* fd, int n) {
static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
static void fd_global_shutdown(void) {
+ // TODO(guantaol): We don't have a reasonable explanation about this
+ // lock()/unlock() pattern. It can be a valid barrier if there is at most one
+ // pending lock() at this point. Otherwise, there is still a possibility of
+ // use-after-free race. Need to reason about the code and/or clean it up.
gpr_mu_lock(&fd_freelist_mu);
gpr_mu_unlock(&fd_freelist_mu);
while (fd_freelist != nullptr) {
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc
deleted file mode 100644
index 5695ac795d..0000000000
--- a/src/core/lib/iomgr/ev_epollsig_linux.cc
+++ /dev/null
@@ -1,1743 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/iomgr/port.h"
-
-#include <grpc/grpc_posix.h>
-#include <grpc/support/log.h>
-
-/* This polling engine is only relevant on linux kernels supporting epoll() */
-#ifdef GRPC_LINUX_EPOLL_CREATE1
-
-#include "src/core/lib/iomgr/ev_epollsig_linux.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <poll.h>
-#include <pthread.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/debug/stats.h"
-#include "src/core/lib/gpr/tls.h"
-#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/gprpp/manual_constructor.h"
-#include "src/core/lib/iomgr/block_annotate.h"
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/iomgr/iomgr_internal.h"
-#include "src/core/lib/iomgr/lockfree_event.h"
-#include "src/core/lib/iomgr/timer.h"
-#include "src/core/lib/iomgr/wakeup_fd_posix.h"
-#include "src/core/lib/profiling/timers.h"
-
-#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker*)1)
-
-#define GRPC_POLLING_TRACE(...) \
- if (grpc_polling_trace.enabled()) { \
- gpr_log(GPR_INFO, __VA_ARGS__); \
- }
-
-static int grpc_wakeup_signal = -1;
-static bool is_grpc_wakeup_signal_initialized = false;
-
-/* Implements the function defined in grpc_posix.h. This function might be
- * called before even calling grpc_init() to set either a different signal to
- * use. If signum == -1, then the use of signals is disabled */
-void grpc_use_signal(int signum) {
- grpc_wakeup_signal = signum;
- is_grpc_wakeup_signal_initialized = true;
-
- if (grpc_wakeup_signal < 0) {
- gpr_log(GPR_INFO,
- "Use of signals is disabled. Epoll engine will not be used");
- } else {
- gpr_log(GPR_INFO, "epoll engine will be using signal: %d",
- grpc_wakeup_signal);
- }
-}
-
-struct polling_island;
-
-typedef enum {
- POLL_OBJ_FD,
- POLL_OBJ_POLLSET,
- POLL_OBJ_POLLSET_SET
-} poll_obj_type;
-
-typedef struct poll_obj {
-#ifndef NDEBUG
- poll_obj_type obj_type;
-#endif
- gpr_mu mu;
- struct polling_island* pi;
-} poll_obj;
-
-const char* poll_obj_string(poll_obj_type po_type) {
- switch (po_type) {
- case POLL_OBJ_FD:
- return "fd";
- case POLL_OBJ_POLLSET:
- return "pollset";
- case POLL_OBJ_POLLSET_SET:
- return "pollset_set";
- }
-
- GPR_UNREACHABLE_CODE(return "UNKNOWN");
-}
-
- /*******************************************************************************
- * Fd Declarations
- */
-
-#define FD_FROM_PO(po) ((grpc_fd*)(po))
-
-struct grpc_fd {
- poll_obj po;
-
- 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;
-
- /* The fd is either closed or we relinquished control of it. In either
- cases, this indicates that the 'fd' on this structure is no longer
- valid */
- bool orphaned;
-
- grpc_core::ManualConstructor<grpc_core::LockfreeEvent> read_closure;
- grpc_core::ManualConstructor<grpc_core::LockfreeEvent> write_closure;
- grpc_core::ManualConstructor<grpc_core::LockfreeEvent> error_closure;
-
- struct grpc_fd* freelist_next;
- grpc_closure* on_done_closure;
-
- grpc_iomgr_object iomgr_object;
-
- /* Do we need to track EPOLLERR events separately? */
- bool track_err;
-};
-
-/* Reference counting for fds */
-#ifndef NDEBUG
-static void fd_ref(grpc_fd* fd, const char* reason, const char* file, int line);
-static void fd_unref(grpc_fd* fd, const char* reason, const char* file,
- int line);
-#define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__)
-#define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__)
-#else
-static void fd_ref(grpc_fd* fd);
-static void fd_unref(grpc_fd* fd);
-#define GRPC_FD_REF(fd, reason) fd_ref(fd)
-#define GRPC_FD_UNREF(fd, reason) fd_unref(fd)
-#endif
-
-static void fd_global_init(void);
-static void fd_global_shutdown(void);
-
-/*******************************************************************************
- * Polling island Declarations
- */
-
-#ifndef NDEBUG
-
-#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__)
-#define PI_UNREF(p, r) pi_unref_dbg((p), (r), __FILE__, __LINE__)
-
-#else
-
-#define PI_ADD_REF(p, r) pi_add_ref((p))
-#define PI_UNREF(p, r) pi_unref((p))
-
-#endif
-
-/* This is also used as grpc_workqueue (by directly casing it) */
-typedef struct polling_island {
- gpr_mu mu;
- /* Ref count. Use PI_ADD_REF() and PI_UNREF() macros to increment/decrement
- the refcount.
- Once the ref count becomes zero, this structure is destroyed which means
- we should ensure that there is never a scenario where a PI_ADD_REF() is
- racing with a PI_UNREF() that just made the ref_count zero. */
- gpr_atm ref_count;
-
- /* Pointer to the polling_island this merged into.
- * merged_to value is only set once in polling_island's lifetime (and that too
- * only if the island is merged with another island). Because of this, we can
- * use gpr_atm type here so that we can do atomic access on this and reduce
- * lock contention on 'mu' mutex.
- *
- * Note that if this field is not NULL (i.e not 0), all the remaining fields
- * (except mu and ref_count) are invalid and must be ignored. */
- gpr_atm merged_to;
-
- /* Number of threads currently polling on this island */
- gpr_atm poller_count;
-
- /* The fd of the underlying epoll set */
- int epoll_fd;
-
- /* The file descriptors in the epoll set */
- size_t fd_cnt;
- size_t fd_capacity;
- grpc_fd** fds;
-} polling_island;
-
-/*******************************************************************************
- * Pollset Declarations
- */
-struct grpc_pollset_worker {
- /* Thread id of this worker */
- pthread_t pt_id;
-
- /* Used to prevent a worker from getting kicked multiple times */
- gpr_atm is_kicked;
- struct grpc_pollset_worker* next;
- struct grpc_pollset_worker* prev;
-};
-
-struct grpc_pollset {
- poll_obj po;
-
- grpc_pollset_worker root_worker;
- bool kicked_without_pollers;
-
- bool shutting_down; /* Is the pollset shutting down ? */
- bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */
- grpc_closure* shutdown_done; /* Called after after shutdown is complete */
-};
-
-/*******************************************************************************
- * Pollset-set Declarations
- */
-struct grpc_pollset_set {
- poll_obj po;
-};
-
-/*******************************************************************************
- * Common helpers
- */
-
-static bool append_error(grpc_error** composite, grpc_error* error,
- const char* desc) {
- if (error == GRPC_ERROR_NONE) return true;
- if (*composite == GRPC_ERROR_NONE) {
- *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc);
- }
- *composite = grpc_error_add_child(*composite, error);
- return false;
-}
-
-/*******************************************************************************
- * Polling island Definitions
- */
-
-/* The wakeup fd that is used to wake up all threads in a Polling island. This
- is useful in the polling island merge operation where we need to wakeup all
- the threads currently polling the smaller polling island (so that they can
- start polling the new/merged polling island)
-
- NOTE: This fd is initialized to be readable and MUST NOT be consumed i.e the
- threads that woke up MUST NOT call grpc_wakeup_fd_consume_wakeup() */
-static grpc_wakeup_fd polling_island_wakeup_fd;
-
-/* The polling island being polled right now.
- See comments in workqueue_maybe_wakeup for why this is tracked. */
-static __thread polling_island* g_current_thread_polling_island;
-
-/* Forward declaration */
-static void polling_island_delete(polling_island* pi);
-
-#ifdef GRPC_TSAN
-/* Currently TSAN may incorrectly flag data races between epoll_ctl and
- epoll_wait for any grpc_fd structs that are added to the epoll set via
- epoll_ctl and are returned (within a very short window) via epoll_wait().
-
- To work-around this race, we establish a happens-before relation between
- the code just-before epoll_ctl() and the code after epoll_wait() by using
- this atomic */
-gpr_atm g_epoll_sync;
-#endif /* defined(GRPC_TSAN) */
-
-static void pi_add_ref(polling_island* pi);
-static void pi_unref(polling_island* pi);
-
-#ifndef NDEBUG
-static void pi_add_ref_dbg(polling_island* pi, const char* reason,
- const char* file, int line) {
- if (grpc_polling_trace.enabled()) {
- gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
- gpr_log(GPR_INFO,
- "Add ref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
- " (%s) - (%s, %d)",
- pi, old_cnt, old_cnt + 1, reason, file, line);
- }
- pi_add_ref(pi);
-}
-
-static void pi_unref_dbg(polling_island* pi, const char* reason,
- const char* file, int line) {
- if (grpc_polling_trace.enabled()) {
- gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
- gpr_log(GPR_INFO,
- "Unref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
- " (%s) - (%s, %d)",
- pi, old_cnt, (old_cnt - 1), reason, file, line);
- }
- pi_unref(pi);
-}
-#endif
-
-static void pi_add_ref(polling_island* pi) {
- gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1);
-}
-
-static void pi_unref(polling_island* pi) {
- /* If ref count went to zero, delete the polling island.
- Note that this deletion not be done under a lock. Once the ref count goes
- to zero, we are guaranteed that no one else holds a reference to the
- polling island (and that there is no racing pi_add_ref() call either).
-
- Also, if we are deleting the polling island and the merged_to field is
- non-empty, we should remove a ref to the merged_to polling island
- */
- if (1 == gpr_atm_full_fetch_add(&pi->ref_count, -1)) {
- polling_island* next = (polling_island*)gpr_atm_acq_load(&pi->merged_to);
- polling_island_delete(pi);
- if (next != nullptr) {
- PI_UNREF(next, "pi_delete"); /* Recursive call */
- }
- }
-}
-
-/* The caller is expected to hold pi->mu lock before calling this function */
-static void polling_island_add_fds_locked(polling_island* pi, grpc_fd** fds,
- size_t fd_count, bool add_fd_refs,
- grpc_error** error) {
- int err;
- size_t i;
- struct epoll_event ev;
- char* err_msg;
- const char* err_desc = "polling_island_add_fds";
-
-#ifdef GRPC_TSAN
- /* See the definition of g_epoll_sync for more context */
- gpr_atm_rel_store(&g_epoll_sync, (gpr_atm)0);
-#endif /* defined(GRPC_TSAN) */
-
- for (i = 0; i < fd_count; i++) {
- ev.events = static_cast<uint32_t>(EPOLLIN | EPOLLOUT | EPOLLET);
- /* Use the least significant bit of ev.data.ptr to store track_err to avoid
- * synchronization issues when accessing it after receiving an event */
- ev.data.ptr = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(fds[i]) |
- (fds[i]->track_err ? 1 : 0));
- err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, fds[i]->fd, &ev);
-
- if (err < 0) {
- if (errno != EEXIST) {
- gpr_asprintf(
- &err_msg,
- "epoll_ctl (epoll_fd: %d) add fd: %d failed with error: %d (%s)",
- pi->epoll_fd, fds[i]->fd, errno, strerror(errno));
- append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc);
- gpr_free(err_msg);
- }
-
- continue;
- }
-
- if (pi->fd_cnt == pi->fd_capacity) {
- pi->fd_capacity = GPR_MAX(pi->fd_capacity + 8, pi->fd_cnt * 3 / 2);
- pi->fds = static_cast<grpc_fd**>(
- gpr_realloc(pi->fds, sizeof(grpc_fd*) * pi->fd_capacity));
- }
-
- pi->fds[pi->fd_cnt++] = fds[i];
- if (add_fd_refs) {
- GRPC_FD_REF(fds[i], "polling_island");
- }
- }
-}
-
-/* The caller is expected to hold pi->mu before calling this */
-static void polling_island_add_wakeup_fd_locked(polling_island* pi,
- grpc_wakeup_fd* wakeup_fd,
- grpc_error** error) {
- struct epoll_event ev;
- int err;
- char* err_msg;
- const char* err_desc = "polling_island_add_wakeup_fd";
-
- ev.events = static_cast<uint32_t>(EPOLLIN | EPOLLET);
- ev.data.ptr = wakeup_fd;
- err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD,
- GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), &ev);
- if (err < 0 && errno != EEXIST) {
- gpr_asprintf(&err_msg,
- "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with "
- "error: %d (%s)",
- pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), errno,
- strerror(errno));
- append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc);
- gpr_free(err_msg);
- }
-}
-
-/* The caller is expected to hold pi->mu lock before calling this function */
-static void polling_island_remove_all_fds_locked(polling_island* pi,
- bool remove_fd_refs,
- grpc_error** error) {
- int err;
- size_t i;
- char* err_msg;
- const char* err_desc = "polling_island_remove_fds";
-
- for (i = 0; i < pi->fd_cnt; i++) {
- err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, pi->fds[i]->fd, nullptr);
- if (err < 0 && errno != ENOENT) {
- gpr_asprintf(&err_msg,
- "epoll_ctl (epoll_fd: %d) delete fds[%zu]: %d failed with "
- "error: %d (%s)",
- pi->epoll_fd, i, pi->fds[i]->fd, errno, strerror(errno));
- append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc);
- gpr_free(err_msg);
- }
-
- if (remove_fd_refs) {
- GRPC_FD_UNREF(pi->fds[i], "polling_island");
- }
- }
-
- pi->fd_cnt = 0;
-}
-
-/* The caller is expected to hold pi->mu lock before calling this function */
-static void polling_island_remove_fd_locked(polling_island* pi, grpc_fd* fd,
- grpc_error** error) {
- int err;
- size_t i;
- char* err_msg;
- const char* err_desc = "polling_island_remove_fd";
-
- /* If fd is already closed, then it would have been automatically been removed
- from the epoll set */
- err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, fd->fd, nullptr);
- if (err < 0 && errno != ENOENT) {
- gpr_asprintf(
- &err_msg,
- "epoll_ctl (epoll_fd: %d) del fd: %d failed with error: %d (%s)",
- pi->epoll_fd, fd->fd, errno, strerror(errno));
- append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc);
- gpr_free(err_msg);
- }
-
- for (i = 0; i < pi->fd_cnt; i++) {
- if (pi->fds[i] == fd) {
- pi->fds[i] = pi->fds[--pi->fd_cnt];
- GRPC_FD_UNREF(fd, "polling_island");
- break;
- }
- }
-}
-
-/* Might return NULL in case of an error */
-static polling_island* polling_island_create(grpc_fd* initial_fd,
- grpc_error** error) {
- polling_island* pi = nullptr;
- const char* err_desc = "polling_island_create";
-
- *error = GRPC_ERROR_NONE;
-
- pi = static_cast<polling_island*>(gpr_malloc(sizeof(*pi)));
- gpr_mu_init(&pi->mu);
- pi->fd_cnt = 0;
- pi->fd_capacity = 0;
- pi->fds = nullptr;
- pi->epoll_fd = -1;
-
- gpr_atm_rel_store(&pi->ref_count, 0);
- gpr_atm_rel_store(&pi->poller_count, 0);
- gpr_atm_rel_store(&pi->merged_to, (gpr_atm) nullptr);
-
- pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-
- if (pi->epoll_fd < 0) {
- append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc);
- goto done;
- }
-
- if (initial_fd != nullptr) {
- polling_island_add_fds_locked(pi, &initial_fd, 1, true, error);
- }
-
-done:
- if (*error != GRPC_ERROR_NONE) {
- polling_island_delete(pi);
- pi = nullptr;
- }
- return pi;
-}
-
-static void polling_island_delete(polling_island* pi) {
- GPR_ASSERT(pi->fd_cnt == 0);
-
- if (pi->epoll_fd >= 0) {
- close(pi->epoll_fd);
- }
- gpr_mu_destroy(&pi->mu);
- gpr_free(pi->fds);
- gpr_free(pi);
-}
-
-/* Attempts to gets the last polling island in the linked list (liked by the
- * 'merged_to' field). Since this does not lock the polling island, there are no
- * guarantees that the island returned is the last island */
-static polling_island* polling_island_maybe_get_latest(polling_island* pi) {
- polling_island* next = (polling_island*)gpr_atm_acq_load(&pi->merged_to);
- while (next != nullptr) {
- pi = next;
- next = (polling_island*)gpr_atm_acq_load(&pi->merged_to);
- }
-
- return pi;
-}
-
-/* Gets the lock on the *latest* polling island i.e the last polling island in
- the linked list (linked by the 'merged_to' field). Call gpr_mu_unlock on the
- returned polling island's mu.
- Usage: To lock/unlock polling island "pi", do the following:
- polling_island *pi_latest = polling_island_lock(pi);
- ...
- ... critical section ..
- ...
- gpr_mu_unlock(&pi_latest->mu); // NOTE: use pi_latest->mu. NOT pi->mu */
-static polling_island* polling_island_lock(polling_island* pi) {
- polling_island* next = nullptr;
-
- while (true) {
- next = (polling_island*)gpr_atm_acq_load(&pi->merged_to);
- if (next == nullptr) {
- /* Looks like 'pi' is the last node in the linked list but unless we check
- this by holding the pi->mu lock, we cannot be sure (i.e without the
- pi->mu lock, we don't prevent island merges).
- To be absolutely sure, check once more by holding the pi->mu lock */
- gpr_mu_lock(&pi->mu);
- next = (polling_island*)gpr_atm_acq_load(&pi->merged_to);
- if (next == nullptr) {
- /* pi is infact the last node and we have the pi->mu lock. we're done */
- break;
- }
-
- /* pi->merged_to is not NULL i.e pi isn't the last node anymore. pi->mu
- * isn't the lock we are interested in. Continue traversing the list */
- gpr_mu_unlock(&pi->mu);
- }
-
- pi = next;
- }
-
- return pi;
-}
-
-/* Gets the lock on the *latest* polling islands in the linked lists pointed by
- *p and *q (and also updates *p and *q to point to the latest polling islands)
-
- This function is needed because calling the following block of code to obtain
- locks on polling islands (*p and *q) is prone to deadlocks.
- {
- polling_island_lock(*p, true);
- polling_island_lock(*q, true);
- }
-
- Usage/example:
- polling_island *p1;
- polling_island *p2;
- ..
- polling_island_lock_pair(&p1, &p2);
- ..
- .. Critical section with both p1 and p2 locked
- ..
- // Release locks: Always call polling_island_unlock_pair() to release locks
- polling_island_unlock_pair(p1, p2);
-*/
-static void polling_island_lock_pair(polling_island** p, polling_island** q) {
- polling_island* pi_1 = *p;
- polling_island* pi_2 = *q;
- polling_island* next_1 = nullptr;
- polling_island* next_2 = nullptr;
-
- /* The algorithm is simple:
- - Go to the last polling islands in the linked lists *pi_1 and *pi_2 (and
- keep updating pi_1 and pi_2)
- - Then obtain locks on the islands by following a lock order rule of
- locking polling_island with lower address first
- Special case: Before obtaining the locks, check if pi_1 and pi_2 are
- pointing to the same island. If that is the case, we can just call
- polling_island_lock()
- - After obtaining both the locks, double check that the polling islands
- are still the last polling islands in their respective linked lists
- (this is because there might have been polling island merges before
- we got the lock)
- - If the polling islands are the last islands, we are done. If not,
- release the locks and continue the process from the first step */
- while (true) {
- next_1 = (polling_island*)gpr_atm_acq_load(&pi_1->merged_to);
- while (next_1 != nullptr) {
- pi_1 = next_1;
- next_1 = (polling_island*)gpr_atm_acq_load(&pi_1->merged_to);
- }
-
- next_2 = (polling_island*)gpr_atm_acq_load(&pi_2->merged_to);
- while (next_2 != nullptr) {
- pi_2 = next_2;
- next_2 = (polling_island*)gpr_atm_acq_load(&pi_2->merged_to);
- }
-
- if (pi_1 == pi_2) {
- pi_1 = pi_2 = polling_island_lock(pi_1);
- break;
- }
-
- if (pi_1 < pi_2) {
- gpr_mu_lock(&pi_1->mu);
- gpr_mu_lock(&pi_2->mu);
- } else {
- gpr_mu_lock(&pi_2->mu);
- gpr_mu_lock(&pi_1->mu);
- }
-
- next_1 = (polling_island*)gpr_atm_acq_load(&pi_1->merged_to);
- next_2 = (polling_island*)gpr_atm_acq_load(&pi_2->merged_to);
- if (next_1 == nullptr && next_2 == nullptr) {
- break;
- }
-
- gpr_mu_unlock(&pi_1->mu);
- gpr_mu_unlock(&pi_2->mu);
- }
-
- *p = pi_1;
- *q = pi_2;
-}
-
-static void polling_island_unlock_pair(polling_island* p, polling_island* q) {
- if (p == q) {
- gpr_mu_unlock(&p->mu);
- } else {
- gpr_mu_unlock(&p->mu);
- gpr_mu_unlock(&q->mu);
- }
-}
-
-static polling_island* polling_island_merge(polling_island* p,
- polling_island* q,
- grpc_error** error) {
- /* Get locks on both the polling islands */
- polling_island_lock_pair(&p, &q);
-
- if (p != q) {
- /* Make sure that p points to the polling island with fewer fds than q */
- if (p->fd_cnt > q->fd_cnt) {
- GPR_SWAP(polling_island*, p, q);
- }
-
- /* Merge p with q i.e move all the fds from p (The one with fewer fds) to q
- Note that the refcounts on the fds being moved will not change here.
- This is why the last param in the following two functions is 'false') */
- polling_island_add_fds_locked(q, p->fds, p->fd_cnt, false, error);
- polling_island_remove_all_fds_locked(p, false, error);
-
- /* Wakeup all the pollers (if any) on p so that they pickup this change */
- polling_island_add_wakeup_fd_locked(p, &polling_island_wakeup_fd, error);
-
- /* Add the 'merged_to' link from p --> q */
- gpr_atm_rel_store(&p->merged_to, (gpr_atm)q);
- PI_ADD_REF(q, "pi_merge"); /* To account for the new incoming ref from p */
- }
- /* else if p == q, nothing needs to be done */
-
- polling_island_unlock_pair(p, q);
-
- /* Return the merged polling island (Note that no merge would have happened
- if p == q which is ok) */
- return q;
-}
-
-static grpc_error* polling_island_global_init() {
- grpc_error* error = GRPC_ERROR_NONE;
-
- error = grpc_wakeup_fd_init(&polling_island_wakeup_fd);
- if (error == GRPC_ERROR_NONE) {
- error = grpc_wakeup_fd_wakeup(&polling_island_wakeup_fd);
- }
-
- return error;
-}
-
-static void polling_island_global_shutdown() {
- grpc_wakeup_fd_destroy(&polling_island_wakeup_fd);
-}
-
-/*******************************************************************************
- * Fd Definitions
- */
-
-/* We need to keep a freelist not because of any concerns of malloc performance
- * but instead so that implementations with multiple threads in (for example)
- * epoll_wait deal with the race between pollset removal and incoming poll
- * notifications.
- *
- * The problem is that the poller ultimately holds a reference to this
- * object, so it is very difficult to know when is safe to free it, at least
- * without some expensive synchronization.
- *
- * If we keep the object freelisted, in the worst case losing this race just
- * becomes a spurious read notification on a reused fd.
- */
-
-/* The alarm system needs to be able to wakeup 'some poller' sometimes
- * (specifically when a new alarm needs to be triggered earlier than the next
- * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a
- * case occurs. */
-
-static grpc_fd* fd_freelist = nullptr;
-static gpr_mu fd_freelist_mu;
-
-#ifndef NDEBUG
-#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
-#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__)
-static void ref_by(grpc_fd* fd, int n, const char* reason, const char* file,
- int line) {
- if (grpc_trace_fd_refcount.enabled()) {
- gpr_log(GPR_DEBUG,
- "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
- fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
- gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
- }
-#else
-#define REF_BY(fd, n, reason) ref_by(fd, n)
-#define UNREF_BY(fd, n, reason) unref_by(fd, n)
-static void ref_by(grpc_fd* fd, int n) {
-#endif
- GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
-}
-
-#ifndef NDEBUG
-static void unref_by(grpc_fd* fd, int n, const char* reason, const char* file,
- int line) {
- if (grpc_trace_fd_refcount.enabled()) {
- gpr_log(GPR_DEBUG,
- "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
- fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
- gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
- }
-#else
-static void unref_by(grpc_fd* fd, int n) {
-#endif
- gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
- if (old == n) {
- /* Add the fd to the freelist */
- gpr_mu_lock(&fd_freelist_mu);
- fd->freelist_next = fd_freelist;
- fd_freelist = fd;
- grpc_iomgr_unregister_object(&fd->iomgr_object);
-
- fd->read_closure->DestroyEvent();
- fd->write_closure->DestroyEvent();
- fd->error_closure->DestroyEvent();
-
- gpr_mu_unlock(&fd_freelist_mu);
- } else {
- GPR_ASSERT(old > n);
- }
-}
-
-/* Increment refcount by two to avoid changing the orphan bit */
-#ifndef NDEBUG
-static void fd_ref(grpc_fd* fd, const char* reason, const char* file,
- int line) {
- ref_by(fd, 2, reason, file, line);
-}
-
-static void fd_unref(grpc_fd* fd, const char* reason, const char* file,
- int line) {
- unref_by(fd, 2, reason, file, line);
-}
-#else
-static void fd_ref(grpc_fd* fd) { ref_by(fd, 2); }
-static void fd_unref(grpc_fd* fd) { unref_by(fd, 2); }
-#endif
-
-static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
-
-static void fd_global_shutdown(void) {
- gpr_mu_lock(&fd_freelist_mu);
- gpr_mu_unlock(&fd_freelist_mu);
- while (fd_freelist != nullptr) {
- grpc_fd* fd = fd_freelist;
- fd_freelist = fd_freelist->freelist_next;
- gpr_mu_destroy(&fd->po.mu);
- gpr_free(fd);
- }
- gpr_mu_destroy(&fd_freelist_mu);
-}
-
-static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
- grpc_fd* new_fd = nullptr;
-
- gpr_mu_lock(&fd_freelist_mu);
- if (fd_freelist != nullptr) {
- new_fd = fd_freelist;
- fd_freelist = fd_freelist->freelist_next;
- }
- gpr_mu_unlock(&fd_freelist_mu);
-
- if (new_fd == nullptr) {
- new_fd = static_cast<grpc_fd*>(gpr_malloc(sizeof(grpc_fd)));
- gpr_mu_init(&new_fd->po.mu);
- new_fd->read_closure.Init();
- new_fd->write_closure.Init();
- new_fd->error_closure.Init();
- }
-
- /* Note: It is not really needed to get the new_fd->po.mu lock here. If this
- * is a newly created fd (or an fd we got from the freelist), no one else
- * would be holding a lock to it anyway. */
- gpr_mu_lock(&new_fd->po.mu);
- new_fd->po.pi = nullptr;
-#ifndef NDEBUG
- new_fd->po.obj_type = POLL_OBJ_FD;
-#endif
-
- gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
- new_fd->fd = fd;
- new_fd->orphaned = false;
- new_fd->read_closure->InitEvent();
- new_fd->write_closure->InitEvent();
- new_fd->error_closure->InitEvent();
- new_fd->track_err = track_err;
-
- new_fd->freelist_next = nullptr;
- new_fd->on_done_closure = nullptr;
-
- gpr_mu_unlock(&new_fd->po.mu);
-
- char* fd_name;
- gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
- grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
- gpr_free(fd_name);
- return new_fd;
-}
-
-static int fd_wrapped_fd(grpc_fd* fd) {
- int ret_fd = -1;
- gpr_mu_lock(&fd->po.mu);
- if (!fd->orphaned) {
- ret_fd = fd->fd;
- }
- gpr_mu_unlock(&fd->po.mu);
-
- return ret_fd;
-}
-
-static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
- const char* reason) {
- grpc_error* error = GRPC_ERROR_NONE;
- polling_island* unref_pi = nullptr;
-
- gpr_mu_lock(&fd->po.mu);
- fd->on_done_closure = on_done;
-
- /* Remove the active status but keep referenced. We want this grpc_fd struct
- to be alive (and not added to freelist) until the end of this function */
- REF_BY(fd, 1, reason);
-
- /* Remove the fd from the polling island:
- - Get a lock on the latest polling island (i.e the last island in the
- linked list pointed by fd->po.pi). This is the island that
- would actually contain the fd
- - Remove the fd from the latest polling island
- - Unlock the latest polling island
- - Set fd->po.pi to NULL (but remove the ref on the polling island
- before doing this.) */
- if (fd->po.pi != nullptr) {
- polling_island* pi_latest = polling_island_lock(fd->po.pi);
- polling_island_remove_fd_locked(pi_latest, fd, &error);
- gpr_mu_unlock(&pi_latest->mu);
-
- unref_pi = fd->po.pi;
- fd->po.pi = nullptr;
- }
-
- /* 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) {
- *release_fd = fd->fd;
- } else {
- close(fd->fd);
- }
-
- fd->orphaned = true;
-
- GRPC_CLOSURE_SCHED(fd->on_done_closure, GRPC_ERROR_REF(error));
-
- gpr_mu_unlock(&fd->po.mu);
- UNREF_BY(fd, 2, reason); /* Drop the reference */
- if (unref_pi != nullptr) {
- /* Unref stale polling island here, outside the fd lock above.
- The polling island owns a workqueue which owns an fd, and unreffing
- inside the lock can cause an eventual lock loop that makes TSAN very
- unhappy. */
- PI_UNREF(unref_pi, "fd_orphan");
- }
- if (error != GRPC_ERROR_NONE) {
- const char* msg = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "fd_orphan: %s", msg);
- }
- GRPC_ERROR_UNREF(error);
-}
-
-static bool fd_is_shutdown(grpc_fd* fd) {
- 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))) {
- shutdown(fd->fd, SHUT_RDWR);
- 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);
-}
-
-static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) {
- fd->write_closure->NotifyOn(closure);
-}
-
-static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) {
- fd->error_closure->NotifyOn(closure);
-}
-
-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_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); }
-
-/*******************************************************************************
- * Pollset Definitions
- */
-GPR_TLS_DECL(g_current_thread_pollset);
-GPR_TLS_DECL(g_current_thread_worker);
-static __thread bool g_initialized_sigmask;
-static __thread sigset_t g_orig_sigmask;
-
-static void sig_handler(int sig_num) {
-#ifdef GRPC_EPOLL_DEBUG
- gpr_log(GPR_INFO, "Received signal %d", sig_num);
-#endif
-}
-
-static void poller_kick_init() { signal(grpc_wakeup_signal, sig_handler); }
-
-/* Global state management */
-static grpc_error* pollset_global_init(void) {
- gpr_tls_init(&g_current_thread_pollset);
- gpr_tls_init(&g_current_thread_worker);
- poller_kick_init();
- return GRPC_ERROR_NONE;
-}
-
-static void pollset_global_shutdown(void) {
- gpr_tls_destroy(&g_current_thread_pollset);
- gpr_tls_destroy(&g_current_thread_worker);
-}
-
-static grpc_error* pollset_worker_kick(grpc_pollset_worker* worker) {
- grpc_error* err = GRPC_ERROR_NONE;
-
- /* Kick the worker only if it was not already kicked */
- if (gpr_atm_no_barrier_cas(&worker->is_kicked, static_cast<gpr_atm>(0),
- static_cast<gpr_atm>(1))) {
- GRPC_POLLING_TRACE(
- "pollset_worker_kick: Kicking worker: %p (thread id: %ld)",
- (void*)worker, (long int)worker->pt_id);
- int err_num = pthread_kill(worker->pt_id, grpc_wakeup_signal);
- if (err_num != 0) {
- err = GRPC_OS_ERROR(err_num, "pthread_kill");
- }
- }
- return err;
-}
-
-/* Return 1 if the pollset has active threads in pollset_work (pollset must
- * be locked) */
-static int pollset_has_workers(grpc_pollset* p) {
- return p->root_worker.next != &p->root_worker;
-}
-
-static void remove_worker(grpc_pollset* p, grpc_pollset_worker* worker) {
- worker->prev->next = worker->next;
- worker->next->prev = worker->prev;
-}
-
-static grpc_pollset_worker* pop_front_worker(grpc_pollset* p) {
- if (pollset_has_workers(p)) {
- grpc_pollset_worker* w = p->root_worker.next;
- remove_worker(p, w);
- return w;
- } else {
- return nullptr;
- }
-}
-
-static void push_back_worker(grpc_pollset* p, grpc_pollset_worker* worker) {
- worker->next = &p->root_worker;
- worker->prev = worker->next->prev;
- worker->prev->next = worker->next->prev = worker;
-}
-
-static void push_front_worker(grpc_pollset* p, grpc_pollset_worker* worker) {
- worker->prev = &p->root_worker;
- worker->next = worker->prev->next;
- worker->prev->next = worker->next->prev = worker;
-}
-
-/* p->mu must be held before calling this function */
-static grpc_error* pollset_kick(grpc_pollset* p,
- grpc_pollset_worker* specific_worker) {
- GPR_TIMER_SCOPE("pollset_kick", 0);
- grpc_error* error = GRPC_ERROR_NONE;
- GRPC_STATS_INC_POLLSET_KICK();
- const char* err_desc = "Kick Failure";
- grpc_pollset_worker* worker = specific_worker;
- if (worker != nullptr) {
- if (worker == GRPC_POLLSET_KICK_BROADCAST) {
- if (pollset_has_workers(p)) {
- GPR_TIMER_SCOPE("pollset_kick.broadcast", 0);
- for (worker = p->root_worker.next; worker != &p->root_worker;
- worker = worker->next) {
- if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) {
- append_error(&error, pollset_worker_kick(worker), err_desc);
- }
- }
- } else {
- p->kicked_without_pollers = true;
- }
- } else {
- GPR_TIMER_MARK("kicked_specifically", 0);
- if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) {
- append_error(&error, pollset_worker_kick(worker), err_desc);
- }
- }
- } else if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)p) {
- /* Since worker == NULL, it means that we can kick "any" worker on this
- pollset 'p'. If 'p' happens to be the same pollset this thread is
- currently polling (i.e in pollset_work() function), then there is no need
- to kick any other worker since the current thread can just absorb the
- kick. This is the reason why we enter this case only when
- g_current_thread_pollset is != p */
-
- GPR_TIMER_MARK("kick_anonymous", 0);
- worker = pop_front_worker(p);
- if (worker != nullptr) {
- GPR_TIMER_MARK("finally_kick", 0);
- push_back_worker(p, worker);
- append_error(&error, pollset_worker_kick(worker), err_desc);
- } else {
- GPR_TIMER_MARK("kicked_no_pollers", 0);
- p->kicked_without_pollers = true;
- }
- }
-
- GRPC_LOG_IF_ERROR("pollset_kick", GRPC_ERROR_REF(error));
- return error;
-}
-
-static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) {
- gpr_mu_init(&pollset->po.mu);
- *mu = &pollset->po.mu;
- pollset->po.pi = nullptr;
-#ifndef NDEBUG
- pollset->po.obj_type = POLL_OBJ_POLLSET;
-#endif
-
- pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker;
- pollset->kicked_without_pollers = false;
-
- pollset->shutting_down = false;
- pollset->finish_shutdown_called = false;
- pollset->shutdown_done = nullptr;
-}
-
-static int poll_deadline_to_millis_timeout(grpc_millis millis) {
- if (millis == GRPC_MILLIS_INF_FUTURE) return -1;
- grpc_millis delta = millis - grpc_core::ExecCtx::Get()->Now();
- if (delta > INT_MAX)
- return INT_MAX;
- else if (delta < 0)
- return 0;
- else
- return static_cast<int>(delta);
-}
-
-static void pollset_release_polling_island(grpc_pollset* ps,
- const char* reason) {
- if (ps->po.pi != nullptr) {
- PI_UNREF(ps->po.pi, reason);
- }
- ps->po.pi = nullptr;
-}
-
-static void finish_shutdown_locked(grpc_pollset* pollset) {
- /* The pollset cannot have any workers if we are at this stage */
- GPR_ASSERT(!pollset_has_workers(pollset));
-
- pollset->finish_shutdown_called = true;
-
- /* Release the ref and set pollset->po.pi to NULL */
- pollset_release_polling_island(pollset, "ps_shutdown");
- GRPC_CLOSURE_SCHED(pollset->shutdown_done, GRPC_ERROR_NONE);
-}
-
-/* pollset->po.mu lock must be held by the caller before calling this */
-static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) {
- GPR_TIMER_SCOPE("pollset_shutdown", 0);
- GPR_ASSERT(!pollset->shutting_down);
- pollset->shutting_down = true;
- pollset->shutdown_done = closure;
- pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
-
- /* If the pollset has any workers, we cannot call finish_shutdown_locked()
- because it would release the underlying polling island. In such a case, we
- let the last worker call finish_shutdown_locked() from pollset_work() */
- if (!pollset_has_workers(pollset)) {
- GPR_ASSERT(!pollset->finish_shutdown_called);
- GPR_TIMER_MARK("pollset_shutdown.finish_shutdown_locked", 0);
- finish_shutdown_locked(pollset);
- }
-}
-
-/* pollset_shutdown is guaranteed to be called before pollset_destroy. So other
- * than destroying the mutexes, there is nothing special that needs to be done
- * here */
-static void pollset_destroy(grpc_pollset* pollset) {
- GPR_ASSERT(!pollset_has_workers(pollset));
- gpr_mu_destroy(&pollset->po.mu);
-}
-
-#define GRPC_EPOLL_MAX_EVENTS 100
-/* Note: sig_mask contains the signal mask to use *during* epoll_wait() */
-static void pollset_work_and_unlock(grpc_pollset* pollset,
- grpc_pollset_worker* worker, int timeout_ms,
- sigset_t* sig_mask, grpc_error** error) {
- GPR_TIMER_SCOPE("pollset_work_and_unlock", 0);
- struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS];
- int epoll_fd = -1;
- int ep_rv;
- polling_island* pi = nullptr;
- char* err_msg;
- const char* err_desc = "pollset_work_and_unlock";
-
- /* We need to get the epoll_fd to wait on. The epoll_fd is in inside the
- latest polling island pointed by pollset->po.pi
-
- Since epoll_fd is immutable, we can read it without obtaining the polling
- island lock. There is however a possibility that the polling island (from
- which we got the epoll_fd) got merged with another island while we are
- in this function. This is still okay because in such a case, we will wakeup
- right-away from epoll_wait() and pick up the latest polling_island the next
- this function (i.e pollset_work_and_unlock()) is called */
-
- if (pollset->po.pi == nullptr) {
- pollset->po.pi = polling_island_create(nullptr, error);
- if (pollset->po.pi == nullptr) {
- return; /* Fatal error. We cannot continue */
- }
-
- PI_ADD_REF(pollset->po.pi, "ps");
- GRPC_POLLING_TRACE("pollset_work: pollset: %p created new pi: %p",
- (void*)pollset, (void*)pollset->po.pi);
- }
-
- pi = polling_island_maybe_get_latest(pollset->po.pi);
- epoll_fd = pi->epoll_fd;
-
- /* Update the pollset->po.pi since the island being pointed by
- pollset->po.pi maybe older than the one pointed by pi) */
- if (pollset->po.pi != pi) {
- /* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the
- polling island to be deleted */
- PI_ADD_REF(pi, "ps");
- PI_UNREF(pollset->po.pi, "ps");
- pollset->po.pi = pi;
- }
-
- /* Add an extra ref so that the island does not get destroyed (which means
- the epoll_fd won't be closed) while we are are doing an epoll_wait() on the
- epoll_fd */
- PI_ADD_REF(pi, "ps_work");
- gpr_mu_unlock(&pollset->po.mu);
-
- gpr_atm_no_barrier_fetch_add(&pi->poller_count, 1);
- g_current_thread_polling_island = pi;
-
- GRPC_SCHEDULING_START_BLOCKING_REGION;
- GRPC_STATS_INC_SYSCALL_POLL();
- ep_rv =
- epoll_pwait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms, sig_mask);
- GRPC_SCHEDULING_END_BLOCKING_REGION;
- if (ep_rv < 0) {
- if (errno != EINTR) {
- gpr_asprintf(&err_msg,
- "epoll_wait() epoll fd: %d failed with error: %d (%s)",
- epoll_fd, errno, strerror(errno));
- append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc);
- } else {
- /* We were interrupted. Save an interation by doing a zero timeout
- epoll_wait to see if there are any other events of interest */
- GRPC_POLLING_TRACE("pollset_work: pollset: %p, worker: %p received kick",
- (void*)pollset, (void*)worker);
- ep_rv = epoll_wait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0);
- }
- }
-
-#ifdef GRPC_TSAN
- /* See the definition of g_poll_sync for more details */
- gpr_atm_acq_load(&g_epoll_sync);
-#endif /* defined(GRPC_TSAN) */
-
- for (int i = 0; i < ep_rv; ++i) {
- void* data_ptr = ep_ev[i].data.ptr;
- if (data_ptr == &polling_island_wakeup_fd) {
- GRPC_POLLING_TRACE(
- "pollset_work: pollset: %p, worker: %p polling island (epoll_fd: "
- "%d) got merged",
- (void*)pollset, (void*)worker, epoll_fd);
- /* This means that our polling island is merged with a different
- island. We do not have to do anything here since the subsequent call
- to the function pollset_work_and_unlock() will pick up the correct
- epoll_fd */
- } else {
- grpc_fd* fd = reinterpret_cast<grpc_fd*>(
- reinterpret_cast<intptr_t>(data_ptr) & ~static_cast<intptr_t>(1));
- bool track_err =
- reinterpret_cast<intptr_t>(data_ptr) & ~static_cast<intptr_t>(1);
- bool cancel = (ep_ev[i].events & EPOLLHUP) != 0;
- bool error = (ep_ev[i].events & EPOLLERR) != 0;
- bool read_ev = (ep_ev[i].events & (EPOLLIN | EPOLLPRI)) != 0;
- bool write_ev = (ep_ev[i].events & EPOLLOUT) != 0;
- bool err_fallback = error && !track_err;
-
- if (error && !err_fallback) {
- fd_has_errors(fd);
- }
- if (read_ev || cancel || err_fallback) {
- fd_become_readable(fd);
- }
- if (write_ev || cancel || err_fallback) {
- fd_become_writable(fd);
- }
- }
- }
-
- g_current_thread_polling_island = nullptr;
- gpr_atm_no_barrier_fetch_add(&pi->poller_count, -1);
-
- GPR_ASSERT(pi != nullptr);
-
- /* Before leaving, release the extra ref we added to the polling island. It
- is important to use "pi" here (i.e our old copy of pollset->po.pi
- that we got before releasing the polling island lock). This is because
- pollset->po.pi pointer might get udpated in other parts of the
- code when there is an island merge while we are doing epoll_wait() above */
- PI_UNREF(pi, "ps_work");
-}
-
-/* pollset->po.mu lock must be held by the caller before calling this.
- The function pollset_work() may temporarily release the lock (pollset->po.mu)
- during the course of its execution but it will always re-acquire the lock and
- ensure that it is held by the time the function returns */
-static grpc_error* pollset_work(grpc_pollset* pollset,
- grpc_pollset_worker** worker_hdl,
- grpc_millis deadline) {
- GPR_TIMER_SCOPE("pollset_work", 0);
- grpc_error* error = GRPC_ERROR_NONE;
- int timeout_ms = poll_deadline_to_millis_timeout(deadline);
-
- sigset_t new_mask;
-
- grpc_pollset_worker worker;
- worker.next = worker.prev = nullptr;
- worker.pt_id = pthread_self();
- gpr_atm_no_barrier_store(&worker.is_kicked, (gpr_atm)0);
-
- if (worker_hdl) *worker_hdl = &worker;
-
- gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
- gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
-
- if (pollset->kicked_without_pollers) {
- /* If the pollset was kicked without pollers, pretend that the current
- worker got the kick and skip polling. A kick indicates that there is some
- work that needs attention like an event on the completion queue or an
- alarm */
- GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0);
- pollset->kicked_without_pollers = 0;
- } else if (!pollset->shutting_down) {
- /* We use the posix-signal with number 'grpc_wakeup_signal' for waking up
- (i.e 'kicking') a worker in the pollset. A 'kick' is a way to inform the
- worker that there is some pending work that needs immediate attention
- (like an event on the completion queue, or a polling island merge that
- results in a new epoll-fd to wait on) and that the worker should not
- spend time waiting in epoll_pwait().
-
- A worker can be kicked anytime from the point it is added to the pollset
- via push_front_worker() (or push_back_worker()) to the point it is
- removed via remove_worker().
- If the worker is kicked before/during it calls epoll_pwait(), it should
- immediately exit from epoll_wait(). If the worker is kicked after it
- returns from epoll_wait(), then nothing really needs to be done.
-
- To accomplish this, we mask 'grpc_wakeup_signal' on this thread at all
- times *except* when it is in epoll_pwait(). This way, the worker never
- misses acting on a kick */
-
- if (!g_initialized_sigmask) {
- sigemptyset(&new_mask);
- sigaddset(&new_mask, grpc_wakeup_signal);
- pthread_sigmask(SIG_BLOCK, &new_mask, &g_orig_sigmask);
- sigdelset(&g_orig_sigmask, grpc_wakeup_signal);
- g_initialized_sigmask = true;
- /* new_mask: The new thread mask which blocks 'grpc_wakeup_signal'.
- This is the mask used at all times *except during
- epoll_wait()*"
- g_orig_sigmask: The thread mask which allows 'grpc_wakeup_signal' and
- this is the mask to use *during epoll_wait()*
-
- The new_mask is set on the worker before it is added to the pollset
- (i.e before it can be kicked) */
- }
-
- push_front_worker(pollset, &worker); /* Add worker to pollset */
-
- pollset_work_and_unlock(pollset, &worker, timeout_ms, &g_orig_sigmask,
- &error);
- grpc_core::ExecCtx::Get()->Flush();
-
- gpr_mu_lock(&pollset->po.mu);
-
- /* Note: There is no need to reset worker.is_kicked to 0 since we are no
- longer going to use this worker */
- remove_worker(pollset, &worker);
- }
-
- /* If we are the last worker on the pollset (i.e pollset_has_workers() is
- false at this point) and the pollset is shutting down, we may have to
- finish the shutdown process by calling finish_shutdown_locked().
- See pollset_shutdown() for more details.
-
- Note: Continuing to access pollset here is safe; it is the caller's
- responsibility to not destroy a pollset when it has outstanding calls to
- pollset_work() */
- if (pollset->shutting_down && !pollset_has_workers(pollset) &&
- !pollset->finish_shutdown_called) {
- GPR_TIMER_MARK("pollset_work.finish_shutdown_locked", 0);
- finish_shutdown_locked(pollset);
-
- gpr_mu_unlock(&pollset->po.mu);
- grpc_core::ExecCtx::Get()->Flush();
- gpr_mu_lock(&pollset->po.mu);
- }
-
- if (worker_hdl) *worker_hdl = nullptr;
-
- gpr_tls_set(&g_current_thread_pollset, (intptr_t)0);
- gpr_tls_set(&g_current_thread_worker, (intptr_t)0);
-
- GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error));
- return error;
-}
-
-static void add_poll_object(poll_obj* bag, poll_obj_type bag_type,
- poll_obj* item, poll_obj_type item_type) {
- GPR_TIMER_SCOPE("add_poll_object", 0);
-
-#ifndef NDEBUG
- GPR_ASSERT(item->obj_type == item_type);
- GPR_ASSERT(bag->obj_type == bag_type);
-#endif
-
- grpc_error* error = GRPC_ERROR_NONE;
- polling_island* pi_new = nullptr;
-
- gpr_mu_lock(&bag->mu);
- gpr_mu_lock(&item->mu);
-
-retry:
- /*
- * 1) If item->pi and bag->pi are both non-NULL and equal, do nothing
- * 2) If item->pi and bag->pi are both NULL, create a new polling island (with
- * a refcount of 2) and point item->pi and bag->pi to the new island
- * 3) If exactly one of item->pi or bag->pi is NULL, update it to point to
- * the other's non-NULL pi
- * 4) Finally if item->pi and bag-pi are non-NULL and not-equal, merge the
- * polling islands and update item->pi and bag->pi to point to the new
- * island
- */
-
- /* Early out if we are trying to add an 'fd' to a 'bag' but the fd is already
- * orphaned */
- if (item_type == POLL_OBJ_FD && (FD_FROM_PO(item))->orphaned) {
- gpr_mu_unlock(&item->mu);
- gpr_mu_unlock(&bag->mu);
- return;
- }
-
- if (item->pi == bag->pi) {
- pi_new = item->pi;
- if (pi_new == nullptr) {
- /* GPR_ASSERT(item->pi == bag->pi == NULL) */
-
- /* If we are adding an fd to a bag (i.e pollset or pollset_set), then
- * we need to do some extra work to make TSAN happy */
- if (item_type == POLL_OBJ_FD) {
- /* Unlock before creating a new polling island: the polling island will
- create a workqueue which creates a file descriptor, and holding an fd
- lock here can eventually cause a loop to appear to TSAN (making it
- unhappy). We don't think it's a real loop (there's an epoch point
- where that loop possibility disappears), but the advantages of
- keeping TSAN happy outweigh any performance advantage we might have
- by keeping the lock held. */
- gpr_mu_unlock(&item->mu);
- pi_new = polling_island_create(FD_FROM_PO(item), &error);
- gpr_mu_lock(&item->mu);
-
- /* Need to reverify any assumptions made between the initial lock and
- getting to this branch: if they've changed, we need to throw away our
- work and figure things out again. */
- if (item->pi != nullptr) {
- GRPC_POLLING_TRACE(
- "add_poll_object: Raced creating new polling island. pi_new: %p "
- "(fd: %d, %s: %p)",
- (void*)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type),
- (void*)bag);
- /* No need to lock 'pi_new' here since this is a new polling island
- and no one has a reference to it yet */
- polling_island_remove_all_fds_locked(pi_new, true, &error);
-
- /* Ref and unref so that the polling island gets deleted during unref
- */
- PI_ADD_REF(pi_new, "dance_of_destruction");
- PI_UNREF(pi_new, "dance_of_destruction");
- goto retry;
- }
- } else {
- pi_new = polling_island_create(nullptr, &error);
- }
-
- GRPC_POLLING_TRACE(
- "add_poll_object: Created new polling island. pi_new: %p (%s: %p, "
- "%s: %p)",
- (void*)pi_new, poll_obj_string(item_type), (void*)item,
- poll_obj_string(bag_type), (void*)bag);
- } else {
- GRPC_POLLING_TRACE(
- "add_poll_object: Same polling island. pi: %p (%s, %s)",
- (void*)pi_new, poll_obj_string(item_type), poll_obj_string(bag_type));
- }
- } else if (item->pi == nullptr) {
- /* GPR_ASSERT(bag->pi != NULL) */
- /* Make pi_new point to latest pi*/
- pi_new = polling_island_lock(bag->pi);
-
- if (item_type == POLL_OBJ_FD) {
- grpc_fd* fd = FD_FROM_PO(item);
- polling_island_add_fds_locked(pi_new, &fd, 1, true, &error);
- }
-
- gpr_mu_unlock(&pi_new->mu);
- GRPC_POLLING_TRACE(
- "add_poll_obj: item->pi was NULL. pi_new: %p (item(%s): %p, "
- "bag(%s): %p)",
- (void*)pi_new, poll_obj_string(item_type), (void*)item,
- poll_obj_string(bag_type), (void*)bag);
- } else if (bag->pi == nullptr) {
- /* GPR_ASSERT(item->pi != NULL) */
- /* Make pi_new to point to latest pi */
- pi_new = polling_island_lock(item->pi);
- gpr_mu_unlock(&pi_new->mu);
- GRPC_POLLING_TRACE(
- "add_poll_obj: bag->pi was NULL. pi_new: %p (item(%s): %p, "
- "bag(%s): %p)",
- (void*)pi_new, poll_obj_string(item_type), (void*)item,
- poll_obj_string(bag_type), (void*)bag);
- } else {
- pi_new = polling_island_merge(item->pi, bag->pi, &error);
- GRPC_POLLING_TRACE(
- "add_poll_obj: polling islands merged. pi_new: %p (item(%s): %p, "
- "bag(%s): %p)",
- (void*)pi_new, poll_obj_string(item_type), (void*)item,
- poll_obj_string(bag_type), (void*)bag);
- }
-
- /* At this point, pi_new is the polling island that both item->pi and bag->pi
- MUST be pointing to */
-
- if (item->pi != pi_new) {
- PI_ADD_REF(pi_new, poll_obj_string(item_type));
- if (item->pi != nullptr) {
- PI_UNREF(item->pi, poll_obj_string(item_type));
- }
- item->pi = pi_new;
- }
-
- if (bag->pi != pi_new) {
- PI_ADD_REF(pi_new, poll_obj_string(bag_type));
- if (bag->pi != nullptr) {
- PI_UNREF(bag->pi, poll_obj_string(bag_type));
- }
- bag->pi = pi_new;
- }
-
- gpr_mu_unlock(&item->mu);
- gpr_mu_unlock(&bag->mu);
-
- GRPC_LOG_IF_ERROR("add_poll_object", error);
-}
-
-static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) {
- add_poll_object(&pollset->po, POLL_OBJ_POLLSET, &fd->po, POLL_OBJ_FD);
-}
-
-/*******************************************************************************
- * Pollset-set Definitions
- */
-
-static grpc_pollset_set* pollset_set_create(void) {
- grpc_pollset_set* pss =
- static_cast<grpc_pollset_set*>(gpr_malloc(sizeof(*pss)));
- gpr_mu_init(&pss->po.mu);
- pss->po.pi = nullptr;
-#ifndef NDEBUG
- pss->po.obj_type = POLL_OBJ_POLLSET_SET;
-#endif
- return pss;
-}
-
-static void pollset_set_destroy(grpc_pollset_set* pss) {
- gpr_mu_destroy(&pss->po.mu);
-
- if (pss->po.pi != nullptr) {
- PI_UNREF(pss->po.pi, "pss_destroy");
- }
-
- gpr_free(pss);
-}
-
-static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) {
- add_poll_object(&pss->po, POLL_OBJ_POLLSET_SET, &fd->po, POLL_OBJ_FD);
-}
-
-static void pollset_set_del_fd(grpc_pollset_set* pss, grpc_fd* fd) {
- /* Nothing to do */
-}
-
-static void pollset_set_add_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
- add_poll_object(&pss->po, POLL_OBJ_POLLSET_SET, &ps->po, POLL_OBJ_POLLSET);
-}
-
-static void pollset_set_del_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
- /* Nothing to do */
-}
-
-static void pollset_set_add_pollset_set(grpc_pollset_set* bag,
- grpc_pollset_set* item) {
- add_poll_object(&bag->po, POLL_OBJ_POLLSET_SET, &item->po,
- POLL_OBJ_POLLSET_SET);
-}
-
-static void pollset_set_del_pollset_set(grpc_pollset_set* bag,
- grpc_pollset_set* item) {
- /* Nothing to do */
-}
-
-/* Test helper functions
- * */
-void* grpc_fd_get_polling_island(grpc_fd* fd) {
- polling_island* pi;
-
- gpr_mu_lock(&fd->po.mu);
- pi = fd->po.pi;
- gpr_mu_unlock(&fd->po.mu);
-
- return pi;
-}
-
-void* grpc_pollset_get_polling_island(grpc_pollset* ps) {
- polling_island* pi;
-
- gpr_mu_lock(&ps->po.mu);
- pi = ps->po.pi;
- gpr_mu_unlock(&ps->po.mu);
-
- return pi;
-}
-
-bool grpc_are_polling_islands_equal(void* p, void* q) {
- polling_island* p1 = static_cast<polling_island*>(p);
- polling_island* p2 = static_cast<polling_island*>(q);
-
- /* Note: polling_island_lock_pair() may change p1 and p2 to point to the
- latest polling islands in their respective linked lists */
- polling_island_lock_pair(&p1, &p2);
- polling_island_unlock_pair(p1, p2);
-
- return p1 == p2;
-}
-
-/*******************************************************************************
- * Event engine binding
- */
-
-static void shutdown_engine(void) {
- fd_global_shutdown();
- pollset_global_shutdown();
- polling_island_global_shutdown();
-}
-
-static const grpc_event_engine_vtable vtable = {
- sizeof(grpc_pollset),
- true,
-
- fd_create,
- fd_wrapped_fd,
- fd_orphan,
- fd_shutdown,
- fd_notify_on_read,
- fd_notify_on_write,
- fd_notify_on_error,
- fd_become_readable,
- fd_become_writable,
- fd_has_errors,
- fd_is_shutdown,
-
- pollset_init,
- pollset_shutdown,
- pollset_destroy,
- pollset_work,
- pollset_kick,
- pollset_add_fd,
-
- pollset_set_create,
- pollset_set_destroy,
- pollset_set_add_pollset,
- pollset_set_del_pollset,
- pollset_set_add_pollset_set,
- pollset_set_del_pollset_set,
- pollset_set_add_fd,
- pollset_set_del_fd,
-
- shutdown_engine,
-};
-
-/* It is possible that GLIBC has epoll but the underlying kernel doesn't.
- * Create a dummy epoll_fd to make sure epoll support is available */
-static bool is_epoll_available() {
- int fd = epoll_create1(EPOLL_CLOEXEC);
- if (fd < 0) {
- gpr_log(
- GPR_ERROR,
- "epoll_create1 failed with error: %d. Not using epoll polling engine",
- fd);
- return false;
- }
- close(fd);
- return true;
-}
-
-const grpc_event_engine_vtable* grpc_init_epollsig_linux(
- bool explicit_request) {
- /* If use of signals is disabled, we cannot use epoll engine*/
- if (is_grpc_wakeup_signal_initialized && grpc_wakeup_signal < 0) {
- gpr_log(GPR_ERROR, "Skipping epollsig because use of signals is disabled.");
- return nullptr;
- }
-
- if (!grpc_has_wakeup_fd()) {
- gpr_log(GPR_ERROR, "Skipping epollsig because of no wakeup fd.");
- return nullptr;
- }
-
- if (!is_epoll_available()) {
- gpr_log(GPR_ERROR, "Skipping epollsig because epoll is unavailable.");
- return nullptr;
- }
-
- if (!is_grpc_wakeup_signal_initialized) {
- if (explicit_request) {
- grpc_use_signal(SIGRTMIN + 6);
- } else {
- gpr_log(GPR_ERROR,
- "Skipping epollsig because uninitialized wakeup signal.");
- return nullptr;
- }
- }
-
- fd_global_init();
-
- if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
- return nullptr;
- }
-
- if (!GRPC_LOG_IF_ERROR("polling_island_global_init",
- polling_island_global_init())) {
- return nullptr;
- }
-
- return &vtable;
-}
-
-#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
-#if defined(GRPC_POSIX_SOCKET_EV_EPOLLSIG)
-#include "src/core/lib/iomgr/ev_epollsig_linux.h"
-/* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means
- epoll_create1 is not available. Return NULL */
-const grpc_event_engine_vtable* grpc_init_epollsig_linux(
- bool explicit_request) {
- return nullptr;
-}
-#endif /* defined(GRPC_POSIX_SOCKET) */
-
-void grpc_use_signal(int signum) {}
-#endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.h b/src/core/lib/iomgr/ev_epollsig_linux.h
deleted file mode 100644
index 2ba2f0a63b..0000000000
--- a/src/core/lib/iomgr/ev_epollsig_linux.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Copyright 2015 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.
- *
- */
-
-#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H
-#define GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/iomgr/port.h"
-
-const grpc_event_engine_vtable* grpc_init_epollsig_linux(bool explicit_request);
-
-#ifdef GRPC_LINUX_EPOLL_CREATE1
-void* grpc_fd_get_polling_island(grpc_fd* fd);
-void* grpc_pollset_get_polling_island(grpc_pollset* ps);
-bool grpc_are_polling_islands_equal(void* p, void* q);
-#endif /* defined(GRPC_LINUX_EPOLL_CREATE1) */
-
-#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H */
diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc
index d4377e2d50..764fb08142 100644
--- a/src/core/lib/iomgr/ev_posix.cc
+++ b/src/core/lib/iomgr/ev_posix.cc
@@ -35,7 +35,6 @@
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/ev_epoll1_linux.h"
#include "src/core/lib/iomgr/ev_epollex_linux.h"
-#include "src/core/lib/iomgr/ev_epollsig_linux.h"
#include "src/core/lib/iomgr/ev_poll_posix.h"
grpc_core::TraceFlag grpc_polling_trace(false,
@@ -123,13 +122,13 @@ const grpc_event_engine_vtable* init_non_polling(bool explicit_request) {
// environment variable if that variable is set (which should be a
// comma-separated list of one or more event engine names)
static event_engine_factory g_factories[] = {
- {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
- {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
- {"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux},
- {"epollsig", grpc_init_epollsig_linux}, {"poll", grpc_init_poll_posix},
- {"poll-cv", grpc_init_poll_cv_posix}, {"none", init_non_polling},
- {ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
- {ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
+ {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
+ {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
+ {"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux},
+ {"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix},
+ {"none", init_non_polling}, {ENGINE_TAIL_CUSTOM, nullptr},
+ {ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
+ {ENGINE_TAIL_CUSTOM, nullptr},
};
static void add(const char* beg, const char* end, char*** ss, size_t* ns) {
@@ -396,4 +395,6 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
g_event_engine->pollset_set_del_fd(pollset_set, fd);
}
+void grpc_use_signal(int signum) {}
+
#endif // GRPC_POSIX_SOCKET_EV
diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h
index 3d459059d7..c8046b21dc 100644
--- a/src/core/lib/iomgr/port.h
+++ b/src/core/lib/iomgr/port.h
@@ -115,7 +115,6 @@
#define GRPC_POSIX_SOCKET_EV 1
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
-#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
#define GRPC_POSIX_SOCKET_EV_POLL 1
#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1
#define GRPC_POSIX_SOCKET_SOCKADDR 1
@@ -183,7 +182,6 @@
#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1
#define GRPC_POSIX_SOCKET_EV 1
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
-#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
#define GRPC_POSIX_SOCKET_EV_POLL 1
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
#define GRPC_POSIX_SOCKET_IOMGR 1
diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc
index ac1e919acb..e40bf81c90 100644
--- a/src/core/lib/iomgr/tcp_posix.cc
+++ b/src/core/lib/iomgr/tcp_posix.cc
@@ -204,6 +204,13 @@ static void drop_uncovered(grpc_tcp* tcp) {
GPR_ASSERT(old_count != 1);
}
+// gRPC API considers a Write operation to be done the moment it clears ‘flow
+// control’ i.e., not necessarily sent on the wire. This means that the
+// application MIGHT not call `grpc_completion_queue_next/pluck` in a timely
+// manner when its `Write()` API is acked.
+//
+// We need to ensure that the fd is 'covered' (i.e being monitored by some
+// polling thread and progress is made) and hence add it to a backup poller here
static void cover_self(grpc_tcp* tcp) {
backup_poller* p;
gpr_atm old_count =
diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc
index 008d37119a..aba5539199 100644
--- a/src/core/lib/iomgr/timer_generic.cc
+++ b/src/core/lib/iomgr/timer_generic.cc
@@ -256,7 +256,7 @@ static grpc_millis compute_min_deadline(timer_shard* shard) {
static void timer_list_init() {
uint32_t i;
- g_num_shards = GPR_MIN(1, 2 * gpr_cpu_num_cores());
+ g_num_shards = GPR_CLAMP(2 * gpr_cpu_num_cores(), 1, 32);
g_shards =
static_cast<timer_shard*>(gpr_zalloc(g_num_shards * sizeof(*g_shards)));
g_shard_queue = static_cast<timer_shard**>(
diff --git a/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc b/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
index 0a39c6c485..118d18d119 100644
--- a/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
+++ b/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
@@ -72,7 +72,8 @@ static void target_service_account_destroy(
static const grpc_alts_credentials_options_vtable vtable = {
alts_client_options_copy, alts_client_options_destroy};
-grpc_alts_credentials_options* grpc_alts_credentials_client_options_create() {
+grpc_alts_credentials_options* grpc_alts_credentials_client_options_create(
+ void) {
auto client_options = static_cast<grpc_alts_credentials_client_options*>(
gpr_zalloc(sizeof(grpc_alts_credentials_client_options)));
client_options->base.vtable = &vtable;
diff --git a/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc b/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc
index 62aa7a620a..1a59c45675 100644
--- a/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc
+++ b/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc
@@ -36,7 +36,8 @@ static void alts_server_options_destroy(
static const grpc_alts_credentials_options_vtable vtable = {
alts_server_options_copy, alts_server_options_destroy};
-grpc_alts_credentials_options* grpc_alts_credentials_server_options_create() {
+grpc_alts_credentials_options* grpc_alts_credentials_server_options_create(
+ void) {
grpc_alts_credentials_server_options* server_options =
static_cast<grpc_alts_credentials_server_options*>(
gpr_zalloc(sizeof(*server_options)));
diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc
index 552e70130a..b99fc5e178 100644
--- a/src/core/lib/security/transport/server_auth_filter.cc
+++ b/src/core/lib/security/transport/server_auth_filter.cc
@@ -41,9 +41,11 @@ struct call_data {
grpc_transport_stream_op_batch* recv_initial_metadata_batch;
grpc_closure* original_recv_initial_metadata_ready;
grpc_closure recv_initial_metadata_ready;
- grpc_error* error;
+ grpc_error* recv_initial_metadata_error;
grpc_closure recv_trailing_metadata_ready;
grpc_closure* original_recv_trailing_metadata_ready;
+ grpc_error* recv_trailing_metadata_error;
+ bool seen_recv_trailing_metadata_ready;
grpc_metadata_array md;
const grpc_metadata* consumed_md;
size_t num_consumed_md;
@@ -114,8 +116,16 @@ static void on_md_processing_done_inner(grpc_call_element* elem,
batch->payload->recv_initial_metadata.recv_initial_metadata,
remove_consumed_md, elem, "Response metadata filtering error");
}
- calld->error = GRPC_ERROR_REF(error);
- GRPC_CLOSURE_SCHED(calld->original_recv_initial_metadata_ready, error);
+ calld->recv_initial_metadata_error = GRPC_ERROR_REF(error);
+ grpc_closure* closure = calld->original_recv_initial_metadata_ready;
+ calld->original_recv_initial_metadata_ready = nullptr;
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error,
+ "continue recv_trailing_metadata_ready");
+ }
+ GRPC_CLOSURE_SCHED(closure, error);
}
// Called from application code.
@@ -184,14 +194,30 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
return;
}
}
- GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready,
- GRPC_ERROR_REF(error));
+ grpc_closure* closure = calld->original_recv_initial_metadata_ready;
+ calld->original_recv_initial_metadata_ready = nullptr;
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error,
+ "continue recv_trailing_metadata_ready");
+ }
+ GRPC_CLOSURE_RUN(closure, GRPC_ERROR_REF(error));
}
static void recv_trailing_metadata_ready(void* user_data, grpc_error* err) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
- err = grpc_error_add_child(GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->error));
+ if (calld->original_recv_initial_metadata_ready != nullptr) {
+ calld->recv_trailing_metadata_error = GRPC_ERROR_REF(err);
+ calld->seen_recv_trailing_metadata_ready = true;
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "deferring recv_trailing_metadata_ready until "
+ "after recv_initial_metadata_ready");
+ return;
+ }
+ err = grpc_error_add_child(
+ GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->recv_initial_metadata_error));
GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err);
}
@@ -249,7 +275,7 @@ static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* ignored) {
call_data* calld = static_cast<call_data*>(elem->call_data);
- GRPC_ERROR_UNREF(calld->error);
+ GRPC_ERROR_UNREF(calld->recv_initial_metadata_error);
}
/* Constructor for channel_data */
diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc
index c2cf450e94..5dc9991f70 100644
--- a/src/core/lib/surface/completion_queue.cc
+++ b/src/core/lib/surface/completion_queue.cc
@@ -184,7 +184,8 @@ static const cq_poller_vtable g_poller_vtable_by_poller_type[] = {
typedef struct cq_vtable {
grpc_cq_completion_type cq_completion_type;
size_t data_size;
- void (*init)(void* data, grpc_core::CQCallbackInterface* shutdown_callback);
+ void (*init)(void* data,
+ grpc_experimental_completion_queue_functor* shutdown_callback);
void (*shutdown)(grpc_completion_queue* cq);
void (*destroy)(void* data);
bool (*begin_op)(grpc_completion_queue* cq, void* tag);
@@ -267,7 +268,7 @@ typedef struct cq_callback_data {
bool shutdown_called;
/** A callback that gets invoked when the CQ completes shutdown */
- grpc_core::CQCallbackInterface* shutdown_callback;
+ grpc_experimental_completion_queue_functor* shutdown_callback;
} cq_callback_data;
/* Completion queue structure */
@@ -333,12 +334,12 @@ static grpc_event cq_pluck(grpc_completion_queue* cq, void* tag,
gpr_timespec deadline, void* reserved);
// Note that cq_init_next and cq_init_pluck do not use the shutdown_callback
-static void cq_init_next(void* data,
- grpc_core::CQCallbackInterface* shutdown_callback);
-static void cq_init_pluck(void* data,
- grpc_core::CQCallbackInterface* shutdown_callback);
-static void cq_init_callback(void* data,
- grpc_core::CQCallbackInterface* shutdown_callback);
+static void cq_init_next(
+ void* data, grpc_experimental_completion_queue_functor* shutdown_callback);
+static void cq_init_pluck(
+ void* data, grpc_experimental_completion_queue_functor* shutdown_callback);
+static void cq_init_callback(
+ void* data, grpc_experimental_completion_queue_functor* shutdown_callback);
static void cq_destroy_next(void* data);
static void cq_destroy_pluck(void* data);
static void cq_destroy_callback(void* data);
@@ -462,7 +463,7 @@ static long cq_event_queue_num_items(grpc_cq_event_queue* q) {
grpc_completion_queue* grpc_completion_queue_create_internal(
grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type,
- grpc_core::CQCallbackInterface* shutdown_callback) {
+ grpc_experimental_completion_queue_functor* shutdown_callback) {
GPR_TIMER_SCOPE("grpc_completion_queue_create_internal", 0);
grpc_completion_queue* cq;
@@ -497,8 +498,8 @@ grpc_completion_queue* grpc_completion_queue_create_internal(
return cq;
}
-static void cq_init_next(void* data,
- grpc_core::CQCallbackInterface* shutdown_callback) {
+static void cq_init_next(
+ void* data, grpc_experimental_completion_queue_functor* shutdown_callback) {
cq_next_data* cqd = static_cast<cq_next_data*>(data);
/* Initial count is dropped by grpc_completion_queue_shutdown */
gpr_atm_no_barrier_store(&cqd->pending_events, 1);
@@ -513,8 +514,8 @@ static void cq_destroy_next(void* data) {
cq_event_queue_destroy(&cqd->queue);
}
-static void cq_init_pluck(void* data,
- grpc_core::CQCallbackInterface* shutdown_callback) {
+static void cq_init_pluck(
+ void* data, grpc_experimental_completion_queue_functor* shutdown_callback) {
cq_pluck_data* cqd = static_cast<cq_pluck_data*>(data);
/* Initial count is dropped by grpc_completion_queue_shutdown */
gpr_atm_no_barrier_store(&cqd->pending_events, 1);
@@ -532,7 +533,7 @@ static void cq_destroy_pluck(void* data) {
}
static void cq_init_callback(
- void* data, grpc_core::CQCallbackInterface* shutdown_callback) {
+ void* data, grpc_experimental_completion_queue_functor* shutdown_callback) {
cq_callback_data* cqd = static_cast<cq_callback_data*>(data);
/* Initial count is dropped by grpc_completion_queue_shutdown */
gpr_atm_no_barrier_store(&cqd->pending_events, 1);
@@ -859,7 +860,8 @@ static void cq_end_op_for_callback(
GRPC_ERROR_UNREF(error);
- (static_cast<grpc_core::CQCallbackInterface*>(tag))->Run(is_success);
+ auto* functor = static_cast<grpc_experimental_completion_queue_functor*>(tag);
+ (*functor->functor_run)(functor, is_success);
}
void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, grpc_error* error,
@@ -1343,7 +1345,7 @@ static void cq_finish_shutdown_callback(grpc_completion_queue* cq) {
GPR_ASSERT(cqd->shutdown_called);
cq->poller_vtable->shutdown(POLLSET_FROM_CQ(cq), &cq->pollset_shutdown_done);
- callback->Run(true);
+ (*callback->functor_run)(callback, true);
}
static void cq_shutdown_callback(grpc_completion_queue* cq) {
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index a7c524d8e8..d60fe6d6ef 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -48,23 +48,6 @@ typedef struct grpc_cq_completion {
uintptr_t next;
} grpc_cq_completion;
-/// For callback CQs, the tag that is passed in for an operation must
-/// actually be a pointer to an implementation of the following class.
-/// When the operation completes, the tag will be typecasted from void*
-/// to grpc_core::CQCallbackInterface* and then the Run method will be
-/// invoked on it. In practice, the language binding (e.g., C++ API
-/// implementation) is responsible for providing and using an implementation
-/// of this abstract base class.
-namespace grpc_core {
-class CQCallbackInterface {
- public:
- virtual ~CQCallbackInterface() {}
- virtual void Run(bool) GRPC_ABSTRACT;
-
- GRPC_ABSTRACT_BASE_CLASS
-};
-} // namespace grpc_core
-
#ifndef NDEBUG
void grpc_cq_internal_ref(grpc_completion_queue* cc, const char* reason,
const char* file, int line);
@@ -106,6 +89,6 @@ int grpc_get_cq_poll_num(grpc_completion_queue* cc);
grpc_completion_queue* grpc_completion_queue_create_internal(
grpc_cq_completion_type completion_type, grpc_cq_polling_type polling_type,
- grpc_core::CQCallbackInterface* shutdown_callback);
+ grpc_experimental_completion_queue_functor* shutdown_callback);
#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */
diff --git a/src/core/lib/surface/completion_queue_factory.cc b/src/core/lib/surface/completion_queue_factory.cc
index ed92dd7eba..2616c156e4 100644
--- a/src/core/lib/surface/completion_queue_factory.cc
+++ b/src/core/lib/surface/completion_queue_factory.cc
@@ -31,8 +31,7 @@ static grpc_completion_queue* default_create(
const grpc_completion_queue_factory* factory,
const grpc_completion_queue_attributes* attr) {
return grpc_completion_queue_create_internal(
- attr->cq_completion_type, attr->cq_polling_type,
- static_cast<grpc_core::CQCallbackInterface*>(attr->cq_shutdown_cb));
+ attr->cq_completion_type, attr->cq_polling_type, attr->cq_shutdown_cb);
}
static grpc_completion_queue_factory_vtable default_vtable = {default_create};
@@ -73,7 +72,8 @@ grpc_completion_queue* grpc_completion_queue_create_for_pluck(void* reserved) {
}
grpc_completion_queue* grpc_completion_queue_create_for_callback(
- void* shutdown_callback, void* reserved) {
+ grpc_experimental_completion_queue_functor* shutdown_callback,
+ void* reserved) {
GPR_ASSERT(!reserved);
grpc_completion_queue_attributes attr = {
2, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback};
diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc
index 5fa58ffdec..72ddc2648d 100644
--- a/src/core/lib/surface/server.cc
+++ b/src/core/lib/surface/server.cc
@@ -150,12 +150,15 @@ struct call_data {
grpc_closure kill_zombie_closure;
grpc_closure* on_done_recv_initial_metadata;
grpc_closure recv_trailing_metadata_ready;
- grpc_error* error;
+ grpc_error* recv_initial_metadata_error;
grpc_closure* original_recv_trailing_metadata_ready;
+ grpc_error* recv_trailing_metadata_error;
+ bool seen_recv_trailing_metadata_ready;
grpc_closure publish;
call_data* pending_next;
+ grpc_call_combiner* call_combiner;
};
struct request_matcher {
@@ -727,21 +730,43 @@ static void server_on_recv_initial_metadata(void* ptr, grpc_error* error) {
if (calld->host_set && calld->path_set) {
/* do nothing */
} else {
+ /* Pass the error reference to calld->recv_initial_metadata_error */
grpc_error* src_error = error;
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
- "Missing :authority or :path", &error, 1);
+ "Missing :authority or :path", &src_error, 1);
GRPC_ERROR_UNREF(src_error);
+ calld->recv_initial_metadata_error = GRPC_ERROR_REF(error);
}
-
- GRPC_CLOSURE_RUN(calld->on_done_recv_initial_metadata, error);
+ grpc_closure* closure = calld->on_done_recv_initial_metadata;
+ calld->on_done_recv_initial_metadata = nullptr;
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error,
+ "continue server_recv_trailing_metadata_ready");
+ }
+ GRPC_CLOSURE_RUN(closure, error);
}
static void server_recv_trailing_metadata_ready(void* user_data,
- grpc_error* err) {
+ grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
- err = grpc_error_add_child(GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->error));
- GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err);
+ if (calld->on_done_recv_initial_metadata != nullptr) {
+ calld->recv_trailing_metadata_error = GRPC_ERROR_REF(error);
+ calld->seen_recv_trailing_metadata_ready = true;
+ GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready,
+ server_recv_trailing_metadata_ready, elem,
+ grpc_schedule_on_exec_ctx);
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "deferring server_recv_trailing_metadata_ready "
+ "until after server_on_recv_initial_metadata");
+ return;
+ }
+ error =
+ grpc_error_add_child(GRPC_ERROR_REF(error),
+ GRPC_ERROR_REF(calld->recv_initial_metadata_error));
+ GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error);
}
static void server_mutate_op(grpc_call_element* elem,
@@ -845,6 +870,7 @@ static grpc_error* init_call_elem(grpc_call_element* elem,
memset(calld, 0, sizeof(call_data));
calld->deadline = GRPC_MILLIS_INF_FUTURE;
calld->call = grpc_call_from_top_element(elem);
+ calld->call_combiner = args->call_combiner;
GRPC_CLOSURE_INIT(&calld->server_on_recv_initial_metadata,
server_on_recv_initial_metadata, elem,
@@ -863,7 +889,7 @@ static void destroy_call_elem(grpc_call_element* elem,
call_data* calld = static_cast<call_data*>(elem->call_data);
GPR_ASSERT(calld->state != PENDING);
- GRPC_ERROR_UNREF(calld->error);
+ GRPC_ERROR_UNREF(calld->recv_initial_metadata_error);
if (calld->host_set) {
grpc_slice_unref_internal(calld->host);
}
diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc
index ad71286e05..31c02893b1 100644
--- a/src/cpp/client/channel_cc.cc
+++ b/src/cpp/client/channel_cc.cc
@@ -20,6 +20,7 @@
#include <chrono>
#include <condition_variable>
+#include <cstring>
#include <memory>
#include <mutex>
@@ -64,6 +65,10 @@ Channel::~Channel() {
namespace {
+inline grpc_slice SliceFromArray(const char* arr, size_t len) {
+ return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len);
+}
+
grpc::string GetChannelInfoField(grpc_channel* channel,
grpc_channel_info* channel_info,
char*** channel_info_field) {
@@ -110,16 +115,17 @@ internal::Call Channel::CreateCall(const internal::RpcMethod& method,
context->propagation_options_.c_bitmask(), cq->cq(),
method.channel_tag(), context->raw_deadline(), nullptr);
} else {
- const char* host_str = nullptr;
- if (!context->authority().empty()) {
- host_str = context->authority_.c_str();
+ const string* host_str = nullptr;
+ if (!context->authority_.empty()) {
+ host_str = &context->authority_;
} else if (!host_.empty()) {
- host_str = host_.c_str();
+ host_str = &host_;
}
- grpc_slice method_slice = SliceFromCopiedString(method.name());
+ grpc_slice method_slice =
+ SliceFromArray(method.name(), strlen(method.name()));
grpc_slice host_slice;
if (host_str != nullptr) {
- host_slice = SliceFromCopiedString(host_str);
+ host_slice = SliceFromCopiedString(*host_str);
}
c_call = grpc_channel_create_call(
c_channel_, context->propagate_from_call_,
@@ -193,17 +199,19 @@ bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed,
}
namespace {
-class ShutdownCallback : public grpc_core::CQCallbackInterface {
+class ShutdownCallback : public grpc_experimental_completion_queue_functor {
public:
+ ShutdownCallback() { functor_run = &ShutdownCallback::Run; }
// TakeCQ takes ownership of the cq into the shutdown callback
// so that the shutdown callback will be responsible for destroying it
void TakeCQ(CompletionQueue* cq) { cq_ = cq; }
// The Run function will get invoked by the completion queue library
// when the shutdown is actually complete
- void Run(bool) override {
- delete cq_;
- grpc_core::Delete(this);
+ static void Run(grpc_experimental_completion_queue_functor* cb, int) {
+ auto* callback = static_cast<ShutdownCallback*>(cb);
+ delete callback->cq_;
+ grpc_core::Delete(callback);
}
private:
diff --git a/src/cpp/common/callback_common.cc b/src/cpp/common/callback_common.cc
deleted file mode 100644
index a0c8eeb516..0000000000
--- a/src/cpp/common/callback_common.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *
- * Copyright 2018 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 <functional>
-
-#include <grpcpp/impl/codegen/callback_common.h>
-#include <grpcpp/impl/codegen/status.h>
-
-#include "src/core/lib/gprpp/memory.h"
-#include "src/core/lib/surface/completion_queue.h"
-
-namespace grpc {
-namespace internal {
-namespace {
-
-template <class Func, class Arg>
-void CatchingCallback(Func&& func, Arg&& arg) {
-#if GRPC_ALLOW_EXCEPTIONS
- try {
- func(arg);
- } catch (...) {
- // nothing to return or change here, just don't crash the library
- }
-#else // GRPC_ALLOW_EXCEPTIONS
- func(arg);
-#endif // GRPC_ALLOW_EXCEPTIONS
-}
-
-class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface {
- public:
- static void operator delete(void* ptr, std::size_t size) {
- assert(size == sizeof(CallbackWithSuccessImpl));
- }
-
- // This operator should never be called as the memory should be freed as part
- // of the arena destruction. It only exists to provide a matching operator
- // delete to the operator new so that some compilers will not complain (see
- // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
- // there are no tests catching the compiler warning.
- static void operator delete(void*, void*) { assert(0); }
-
- CallbackWithSuccessImpl(grpc_call* call, CallbackWithSuccessTag* parent,
- std::function<void(bool)> f)
- : call_(call), parent_(parent), func_(std::move(f)) {
- grpc_call_ref(call);
- }
-
- void Run(bool ok) override {
- void* ignored = parent_->ops();
- bool new_ok = ok;
- GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &new_ok));
- GPR_ASSERT(ignored == parent_->ops());
-
- // Last use of func_, so ok to move it out for rvalue call above
- CatchingCallback(std::move(func_), ok);
-
- func_ = nullptr; // reset to clear this out for sure
- grpc_call_unref(call_);
- }
-
- private:
- grpc_call* call_;
- CallbackWithSuccessTag* parent_;
- std::function<void(bool)> func_;
-};
-
-class CallbackWithStatusImpl : public grpc_core::CQCallbackInterface {
- public:
- static void operator delete(void* ptr, std::size_t size) {
- assert(size == sizeof(CallbackWithStatusImpl));
- }
-
- // This operator should never be called as the memory should be freed as part
- // of the arena destruction. It only exists to provide a matching operator
- // delete to the operator new so that some compilers will not complain (see
- // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
- // there are no tests catching the compiler warning.
- static void operator delete(void*, void*) { assert(0); }
-
- CallbackWithStatusImpl(grpc_call* call, CallbackWithStatusTag* parent,
- std::function<void(Status)> f)
- : call_(call), parent_(parent), func_(std::move(f)), status_() {
- grpc_call_ref(call);
- }
-
- void Run(bool ok) override {
- void* ignored = parent_->ops();
-
- GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &ok));
- GPR_ASSERT(ignored == parent_->ops());
-
- // Last use of func_ or status_, so ok to move them out
- CatchingCallback(std::move(func_), std::move(status_));
-
- func_ = nullptr; // reset to clear this out for sure
- grpc_call_unref(call_);
- }
- Status* status_ptr() { return &status_; }
-
- private:
- grpc_call* call_;
- CallbackWithStatusTag* parent_;
- std::function<void(Status)> func_;
- Status status_;
-};
-
-} // namespace
-
-CallbackWithSuccessTag::CallbackWithSuccessTag(grpc_call* call,
- std::function<void(bool)> f,
- CompletionQueueTag* ops)
- : impl_(new (grpc_call_arena_alloc(call, sizeof(CallbackWithSuccessImpl)))
- CallbackWithSuccessImpl(call, this, std::move(f))),
- ops_(ops) {}
-
-void CallbackWithSuccessTag::force_run(bool ok) { impl_->Run(ok); }
-
-CallbackWithStatusTag::CallbackWithStatusTag(grpc_call* call,
- std::function<void(Status)> f,
- CompletionQueueTag* ops)
- : ops_(ops) {
- auto* impl = new (grpc_call_arena_alloc(call, sizeof(CallbackWithStatusImpl)))
- CallbackWithStatusImpl(call, this, std::move(f));
- impl_ = impl;
- status_ = impl->status_ptr();
-}
-
-void CallbackWithStatusTag::force_run(Status s) {
- *status_ = std::move(s);
- impl_->Run(true);
-}
-
-} // namespace internal
-} // namespace grpc
diff --git a/src/cpp/server/channelz/channelz_service.cc b/src/cpp/server/channelz/channelz_service.cc
index e096c1f421..4e3fe8c1c9 100644
--- a/src/cpp/server/channelz/channelz_service.cc
+++ b/src/cpp/server/channelz/channelz_service.cc
@@ -92,4 +92,21 @@ Status ChannelzService::GetSubchannel(
return Status::OK;
}
+Status ChannelzService::GetSocket(ServerContext* unused,
+ const channelz::v1::GetSocketRequest* request,
+ channelz::v1::GetSocketResponse* response) {
+ char* json_str = grpc_channelz_get_socket(request->socket_id());
+ gpr_log(GPR_ERROR, "%s", json_str);
+ if (json_str == nullptr) {
+ return Status(NOT_FOUND, "No object found for that SocketId");
+ }
+ google::protobuf::util::Status s =
+ google::protobuf::util::JsonStringToMessage(json_str, response);
+ gpr_free(json_str);
+ if (s != google::protobuf::util::Status::OK) {
+ return Status(INTERNAL, s.ToString());
+ }
+ return Status::OK;
+}
+
} // namespace grpc
diff --git a/src/cpp/server/channelz/channelz_service.h b/src/cpp/server/channelz/channelz_service.h
index 9e0b5b6ead..1be4e01c73 100644
--- a/src/cpp/server/channelz/channelz_service.h
+++ b/src/cpp/server/channelz/channelz_service.h
@@ -44,6 +44,10 @@ class ChannelzService final : public channelz::v1::Channelz::Service {
Status GetSubchannel(ServerContext* unused,
const channelz::v1::GetSubchannelRequest* request,
channelz::v1::GetSubchannelResponse* response) override;
+ // implementation of GetSocket rpc
+ Status GetSocket(ServerContext* unused,
+ const channelz::v1::GetSocketRequest* request,
+ channelz::v1::GetSocketResponse* response) override;
};
} // namespace grpc
diff --git a/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs b/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs
new file mode 100644
index 0000000000..c3aee726f2
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs
@@ -0,0 +1,119 @@
+#region Copyright notice and license
+
+// Copyright 2018 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;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class ContextualMarshallerTest
+ {
+ const string Host = "127.0.0.1";
+
+ MockServiceHelper helper;
+ Server server;
+ Channel channel;
+
+ [SetUp]
+ public void Init()
+ {
+ var contextualMarshaller = new Marshaller<string>(
+ (str, serializationContext) =>
+ {
+ if (str == "UNSERIALIZABLE_VALUE")
+ {
+ // Google.Protobuf throws exception inherited from IOException
+ throw new IOException("Error serializing the message.");
+ }
+ if (str == "SERIALIZE_TO_NULL")
+ {
+ return;
+ }
+ var bytes = System.Text.Encoding.UTF8.GetBytes(str);
+ serializationContext.Complete(bytes);
+ },
+ (deserializationContext) =>
+ {
+ var buffer = deserializationContext.PayloadAsNewBuffer();
+ Assert.AreEqual(buffer.Length, deserializationContext.PayloadLength);
+ var s = System.Text.Encoding.UTF8.GetString(buffer);
+ if (s == "UNPARSEABLE_VALUE")
+ {
+ // Google.Protobuf throws exception inherited from IOException
+ throw new IOException("Error parsing the message.");
+ }
+ return s;
+ });
+ helper = new MockServiceHelper(Host, contextualMarshaller);
+ server = helper.GetServer();
+ server.Start();
+ channel = helper.GetChannel();
+ }
+
+ [TearDown]
+ public void Cleanup()
+ {
+ channel.ShutdownAsync().Wait();
+ server.ShutdownAsync().Wait();
+ }
+
+ [Test]
+ public void UnaryCall()
+ {
+ helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+ {
+ return Task.FromResult(request);
+ });
+ Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC"));
+ }
+
+ [Test]
+ public void ResponseParsingError_UnaryResponse()
+ {
+ helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+ {
+ return Task.FromResult("UNPARSEABLE_VALUE");
+ });
+
+ var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST"));
+ Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
+ }
+
+ [Test]
+ public void RequestSerializationError_BlockingUnary()
+ {
+ Assert.Throws<IOException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE"));
+ }
+
+ [Test]
+ public void SerializationResultIsNull_BlockingUnary()
+ {
+ Assert.Throws<NullReferenceException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "SERIALIZE_TO_NULL"));
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/MarshallerTest.cs b/src/csharp/Grpc.Core.Tests/MarshallerTest.cs
new file mode 100644
index 0000000000..97f64a0575
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/MarshallerTest.cs
@@ -0,0 +1,105 @@
+#region Copyright notice and license
+
+// Copyright 2018 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;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class MarshallerTest
+ {
+ [Test]
+ public void ContextualSerializerEmulation()
+ {
+ Func<string, byte[]> simpleSerializer = System.Text.Encoding.UTF8.GetBytes;
+ Func<byte[], string> simpleDeserializer = System.Text.Encoding.UTF8.GetString;
+ var marshaller = new Marshaller<string>(simpleSerializer,
+ simpleDeserializer);
+
+ Assert.AreSame(simpleSerializer, marshaller.Serializer);
+ Assert.AreSame(simpleDeserializer, marshaller.Deserializer);
+
+ // test that emulated contextual serializer and deserializer work
+ string origMsg = "abc";
+ var serializationContext = new FakeSerializationContext();
+ marshaller.ContextualSerializer(origMsg, serializationContext);
+
+ var deserializationContext = new FakeDeserializationContext(serializationContext.Payload);
+ Assert.AreEqual(origMsg, marshaller.ContextualDeserializer(deserializationContext));
+ }
+
+ [Test]
+ public void SimpleSerializerEmulation()
+ {
+ Action<string, SerializationContext> contextualSerializer = (str, context) =>
+ {
+ var bytes = System.Text.Encoding.UTF8.GetBytes(str);
+ context.Complete(bytes);
+ };
+ Func<DeserializationContext, string> contextualDeserializer = (context) =>
+ {
+ return System.Text.Encoding.UTF8.GetString(context.PayloadAsNewBuffer());
+ };
+ var marshaller = new Marshaller<string>(contextualSerializer, contextualDeserializer);
+
+ Assert.AreSame(contextualSerializer, marshaller.ContextualSerializer);
+ Assert.AreSame(contextualDeserializer, marshaller.ContextualDeserializer);
+
+ // test that emulated serializer and deserializer work
+ var origMsg = "abc";
+ var serialized = marshaller.Serializer(origMsg);
+ Assert.AreEqual(origMsg, marshaller.Deserializer(serialized));
+ }
+
+ class FakeSerializationContext : SerializationContext
+ {
+ public byte[] Payload;
+ public override void Complete(byte[] payload)
+ {
+ this.Payload = payload;
+ }
+ }
+
+ class FakeDeserializationContext : DeserializationContext
+ {
+ public byte[] payload;
+
+ public FakeDeserializationContext(byte[] payload)
+ {
+ this.payload = payload;
+ }
+
+ public override int PayloadLength => payload.Length;
+
+ public override byte[] PayloadAsNewBuffer()
+ {
+ return payload;
+ }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/MetadataTest.cs b/src/csharp/Grpc.Core.Tests/MetadataTest.cs
index 171c5c470e..d85d7572a6 100644
--- a/src/csharp/Grpc.Core.Tests/MetadataTest.cs
+++ b/src/csharp/Grpc.Core.Tests/MetadataTest.cs
@@ -73,6 +73,23 @@ namespace Grpc.Core.Tests
}
[Test]
+ public void KeysAreNormalized_UppercaseKey()
+ {
+ var uppercaseKey = "ABC";
+ var entry = new Metadata.Entry(uppercaseKey, "XYZ");
+ Assert.AreEqual("abc", entry.Key);
+ }
+
+ [Test]
+ public void KeysAreNormalized_LowercaseKey()
+ {
+ var lowercaseKey = "abc";
+ var entry = new Metadata.Entry(lowercaseKey, "XYZ");
+ // no allocation if key already lowercase
+ Assert.AreSame(lowercaseKey, entry.Key);
+ }
+
+ [Test]
public void Entry_ConstructionPreconditions()
{
Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry(null, "xyz"));
diff --git a/src/csharp/Grpc.Core/ClientBase.cs b/src/csharp/Grpc.Core/ClientBase.cs
index fac34071be..05edce7467 100644
--- a/src/csharp/Grpc.Core/ClientBase.cs
+++ b/src/csharp/Grpc.Core/ClientBase.cs
@@ -151,12 +151,12 @@ namespace Grpc.Core
{
private class ClientBaseConfigurationInterceptor : Interceptor
{
- readonly Func<IMethod, string, CallOptions, Tuple<string, CallOptions>> interceptor;
+ readonly Func<IMethod, string, CallOptions, ClientBaseConfigurationInfo> interceptor;
/// <summary>
/// Creates a new instance of ClientBaseConfigurationInterceptor given the specified header and host interceptor function.
/// </summary>
- public ClientBaseConfigurationInterceptor(Func<IMethod, string, CallOptions, Tuple<string, CallOptions>> interceptor)
+ public ClientBaseConfigurationInterceptor(Func<IMethod, string, CallOptions, ClientBaseConfigurationInfo> interceptor)
{
this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor));
}
@@ -166,7 +166,7 @@ namespace Grpc.Core
where TResponse : class
{
var newHostAndCallOptions = interceptor(context.Method, context.Host, context.Options);
- return new ClientInterceptorContext<TRequest, TResponse>(context.Method, newHostAndCallOptions.Item1, newHostAndCallOptions.Item2);
+ return new ClientInterceptorContext<TRequest, TResponse>(context.Method, newHostAndCallOptions.Host, newHostAndCallOptions.CallOptions);
}
public override TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)
@@ -195,6 +195,18 @@ namespace Grpc.Core
}
}
+ internal struct ClientBaseConfigurationInfo
+ {
+ internal readonly string Host;
+ internal readonly CallOptions CallOptions;
+
+ internal ClientBaseConfigurationInfo(string host, CallOptions callOptions)
+ {
+ Host = host;
+ CallOptions = callOptions;
+ }
+ }
+
readonly CallInvoker undecoratedCallInvoker;
readonly string host;
@@ -206,7 +218,7 @@ namespace Grpc.Core
internal CallInvoker CreateDecoratedCallInvoker()
{
- return undecoratedCallInvoker.Intercept(new ClientBaseConfigurationInterceptor((method, host, options) => Tuple.Create(this.host, options)));
+ return undecoratedCallInvoker.Intercept(new ClientBaseConfigurationInterceptor((method, host, options) => new ClientBaseConfigurationInfo(this.host, options)));
}
internal ClientBaseConfiguration WithHost(string host)
diff --git a/src/csharp/Grpc.Core/DeserializationContext.cs b/src/csharp/Grpc.Core/DeserializationContext.cs
new file mode 100644
index 0000000000..5b6372ef85
--- /dev/null
+++ b/src/csharp/Grpc.Core/DeserializationContext.cs
@@ -0,0 +1,46 @@
+#region Copyright notice and license
+
+// Copyright 2018 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
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// Provides access to the payload being deserialized when deserializing messages.
+ /// </summary>
+ public abstract class DeserializationContext
+ {
+ /// <summary>
+ /// Get the total length of the payload in bytes.
+ /// </summary>
+ public abstract int PayloadLength { get; }
+
+ /// <summary>
+ /// Gets the entire payload as a newly allocated byte array.
+ /// Once the byte array is returned, the byte array becomes owned by the caller and won't be ever accessed or reused by gRPC again.
+ /// NOTE: Obtaining the buffer as a newly allocated byte array is the simplest way of accessing the payload,
+ /// but it can have important consequences in high-performance scenarios.
+ /// In particular, using this method usually requires copying of the entire buffer one extra time.
+ /// Also, allocating a new buffer each time can put excessive pressure on GC, especially if
+ /// the payload is more than 86700 bytes large (which means the newly allocated buffer will be placed in LOH,
+ /// and LOH object can only be garbage collected via a full ("stop the world") GC run).
+ /// NOTE: Deserializers are expected not to call this method more than once per received message
+ /// (as there is no practical reason for doing so) and <c>DeserializationContext</c> implementations are free to assume so.
+ /// </summary>
+ /// <returns>byte array containing the entire payload.</returns>
+ public abstract byte[] PayloadAsNewBuffer();
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/MarshalUtils.cs b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs
index 3f9605bfdd..09ded1a036 100644
--- a/src/csharp/Grpc.Core/Internal/MarshalUtils.cs
+++ b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs
@@ -35,6 +35,13 @@ namespace Grpc.Core.Internal
/// </summary>
public static string PtrToStringUTF8(IntPtr ptr, int len)
{
+ if (len == 0)
+ {
+ return "";
+ }
+
+ // TODO(jtattermusch): once Span dependency is added,
+ // use Span-based API to decode the string without copying the buffer.
var bytes = new byte[len];
Marshal.Copy(ptr, bytes, 0, len);
return EncodingUTF8.GetString(bytes);
diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs
index 1d758ca935..0af9aa586b 100644
--- a/src/csharp/Grpc.Core/Marshaller.cs
+++ b/src/csharp/Grpc.Core/Marshaller.cs
@@ -29,36 +29,129 @@ namespace Grpc.Core
readonly Func<T, byte[]> serializer;
readonly Func<byte[], T> deserializer;
+ readonly Action<T, SerializationContext> contextualSerializer;
+ readonly Func<DeserializationContext, T> contextualDeserializer;
+
/// <summary>
- /// Initializes a new marshaller.
+ /// Initializes a new marshaller from simple serialize/deserialize functions.
/// </summary>
/// <param name="serializer">Function that will be used to serialize messages.</param>
/// <param name="deserializer">Function that will be used to deserialize messages.</param>
public Marshaller(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
{
- this.serializer = GrpcPreconditions.CheckNotNull(serializer, "serializer");
- this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, "deserializer");
+ this.serializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
+ this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
+ this.contextualSerializer = EmulateContextualSerializer;
+ this.contextualDeserializer = EmulateContextualDeserializer;
}
/// <summary>
- /// Gets the serializer function.
+ /// Initializes a new marshaller from serialize/deserialize fuctions that can access serialization and deserialization
+ /// context. Compared to the simple serializer/deserializer functions, using the contextual version provides more
+ /// flexibility and can lead to increased efficiency (and better performance).
+ /// Note: This constructor is part of an experimental API that can change or be removed without any prior notice.
/// </summary>
- public Func<T, byte[]> Serializer
+ /// <param name="serializer">Function that will be used to serialize messages.</param>
+ /// <param name="deserializer">Function that will be used to deserialize messages.</param>
+ public Marshaller(Action<T, SerializationContext> serializer, Func<DeserializationContext, T> deserializer)
{
- get
- {
- return this.serializer;
- }
+ this.contextualSerializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
+ this.contextualDeserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
+ // TODO(jtattermusch): once gRPC C# library switches to using contextual (de)serializer,
+ // emulating the simple (de)serializer will become unnecessary.
+ this.serializer = EmulateSimpleSerializer;
+ this.deserializer = EmulateSimpleDeserializer;
}
/// <summary>
+ /// Gets the serializer function.
+ /// </summary>
+ public Func<T, byte[]> Serializer => this.serializer;
+
+ /// <summary>
/// Gets the deserializer function.
/// </summary>
- public Func<byte[], T> Deserializer
+ public Func<byte[], T> Deserializer => this.deserializer;
+
+ /// <summary>
+ /// Gets the serializer function.
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public Action<T, SerializationContext> ContextualSerializer => this.contextualSerializer;
+
+ /// <summary>
+ /// Gets the serializer function.
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public Func<DeserializationContext, T> ContextualDeserializer => this.contextualDeserializer;
+
+ // for backward compatibility, emulate the simple serializer using the contextual one
+ private byte[] EmulateSimpleSerializer(T msg)
{
- get
+ // TODO(jtattermusch): avoid the allocation by passing a thread-local instance
+ // This code will become unnecessary once gRPC C# library switches to using contextual (de)serializer.
+ var context = new EmulatedSerializationContext();
+ this.contextualSerializer(msg, context);
+ return context.GetPayload();
+ }
+
+ // for backward compatibility, emulate the simple deserializer using the contextual one
+ private T EmulateSimpleDeserializer(byte[] payload)
+ {
+ // TODO(jtattermusch): avoid the allocation by passing a thread-local instance
+ // This code will become unnecessary once gRPC C# library switches to using contextual (de)serializer.
+ var context = new EmulatedDeserializationContext(payload);
+ return this.contextualDeserializer(context);
+ }
+
+ // for backward compatibility, emulate the contextual serializer using the simple one
+ private void EmulateContextualSerializer(T message, SerializationContext context)
+ {
+ var payload = this.serializer(message);
+ context.Complete(payload);
+ }
+
+ // for backward compatibility, emulate the contextual deserializer using the simple one
+ private T EmulateContextualDeserializer(DeserializationContext context)
+ {
+ return this.deserializer(context.PayloadAsNewBuffer());
+ }
+
+ internal class EmulatedSerializationContext : SerializationContext
+ {
+ bool isComplete;
+ byte[] payload;
+
+ public override void Complete(byte[] payload)
+ {
+ GrpcPreconditions.CheckState(!isComplete);
+ this.isComplete = true;
+ this.payload = payload;
+ }
+
+ internal byte[] GetPayload()
+ {
+ return this.payload;
+ }
+ }
+
+ internal class EmulatedDeserializationContext : DeserializationContext
+ {
+ readonly byte[] payload;
+ bool alreadyCalledPayloadAsNewBuffer;
+
+ public EmulatedDeserializationContext(byte[] payload)
+ {
+ this.payload = GrpcPreconditions.CheckNotNull(payload);
+ }
+
+ public override int PayloadLength => payload.Length;
+
+ public override byte[] PayloadAsNewBuffer()
{
- return this.deserializer;
+ GrpcPreconditions.CheckState(!alreadyCalledPayloadAsNewBuffer);
+ alreadyCalledPayloadAsNewBuffer = true;
+ return payload;
}
}
}
@@ -77,6 +170,15 @@ namespace Grpc.Core
}
/// <summary>
+ /// Creates a marshaller from specified contextual serializer and deserializer.
+ /// Note: This method is part of an experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public static Marshaller<T> Create<T>(Action<T, SerializationContext> serializer, Func<DeserializationContext, T> deserializer)
+ {
+ return new Marshaller<T>(serializer, deserializer);
+ }
+
+ /// <summary>
/// Returns a marshaller for <c>string</c> type. This is useful for testing.
/// </summary>
public static Marshaller<string> StringMarshaller
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
index 281952d6d4..bc263c3469 100644
--- a/src/csharp/Grpc.Core/Metadata.cs
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -135,7 +135,7 @@ namespace Grpc.Core
}
/// <summary>
- /// <see cref="T:IList`1"/>
+ /// Adds a new ASCII-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
/// </summary>
public void Add(string key, string value)
{
@@ -143,7 +143,7 @@ namespace Grpc.Core
}
/// <summary>
- /// <see cref="T:IList`1"/>
+ /// Adds a new binary-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
/// </summary>
public void Add(string key, byte[] valueBytes)
{
@@ -225,8 +225,6 @@ namespace Grpc.Core
/// </summary>
public class Entry
{
- private static readonly Regex ValidKeyRegex = new Regex("^[.a-z0-9_-]+$");
-
readonly string key;
readonly string value;
readonly byte[] valueBytes;
@@ -241,7 +239,7 @@ namespace Grpc.Core
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.Metadata.Entry"/> struct with a binary value.
/// </summary>
- /// <param name="key">Metadata key, needs to have suffix indicating a binary valued metadata entry.</param>
+ /// <param name="key">Metadata key. Gets converted to lowercase. Needs to have suffix indicating a binary valued metadata entry. Can only contain lowercase alphanumeric characters, underscores, hyphens and dots.</param>
/// <param name="valueBytes">Value bytes.</param>
public Entry(string key, byte[] valueBytes)
{
@@ -255,9 +253,9 @@ namespace Grpc.Core
}
/// <summary>
- /// Initializes a new instance of the <see cref="Grpc.Core.Metadata.Entry"/> struct holding an ASCII value.
+ /// Initializes a new instance of the <see cref="Grpc.Core.Metadata.Entry"/> struct with an ASCII value.
/// </summary>
- /// <param name="key">Metadata key, must not use suffix indicating a binary valued metadata entry.</param>
+ /// <param name="key">Metadata key. Gets converted to lowercase. Must not use suffix indicating a binary valued metadata entry. Can only contain lowercase alphanumeric characters, underscores, hyphens and dots.</param>
/// <param name="value">Value string. Only ASCII characters are allowed.</param>
public Entry(string key, string value)
{
@@ -358,10 +356,42 @@ namespace Grpc.Core
private static string NormalizeKey(string key)
{
- var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLowerInvariant();
- GrpcPreconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized),
+ GrpcPreconditions.CheckNotNull(key, "key");
+
+ GrpcPreconditions.CheckArgument(IsValidKey(key, out bool isLowercase),
"Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores, hyphens and dots.");
- return normalized;
+ if (isLowercase)
+ {
+ // save allocation of a new string if already lowercase
+ return key;
+ }
+
+ return key.ToLowerInvariant();
+ }
+
+ private static bool IsValidKey(string input, out bool isLowercase)
+ {
+ isLowercase = true;
+ for (int i = 0; i < input.Length; i++)
+ {
+ char c = input[i];
+ if ('a' <= c && c <= 'z' ||
+ '0' <= c && c <= '9' ||
+ c == '.' ||
+ c == '_' ||
+ c == '-' )
+ continue;
+
+ if ('A' <= c && c <= 'Z')
+ {
+ isLowercase = false;
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/SerializationContext.cs b/src/csharp/Grpc.Core/SerializationContext.cs
new file mode 100644
index 0000000000..cf4d1595da
--- /dev/null
+++ b/src/csharp/Grpc.Core/SerializationContext.cs
@@ -0,0 +1,34 @@
+#region Copyright notice and license
+
+// Copyright 2018 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
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// Provides storage for payload when serializing a message.
+ /// </summary>
+ public abstract class SerializationContext
+ {
+ /// <summary>
+ /// Use the byte array as serialized form of current message and mark serialization process as complete.
+ /// Complete() can only be called once. By calling this method the caller gives up the ownership of the
+ /// payload which must not be accessed afterwards.
+ /// </summary>
+ /// <param name="payload">the serialized form of current message</param>
+ public abstract void Complete(byte[] payload);
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index ad7033b782..8daf3fa98b 100755
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -18,7 +18,7 @@
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="$(GoogleProtobufVersion)" />
- <PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
+ <PackageReference Include="CommandLineParser" Version="2.3.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnitLite" Version="3.10.1" />
</ItemGroup>
diff --git a/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj
index 8a629f9748..d39d46cf1b 100644
--- a/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj
+++ b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj
@@ -16,7 +16,7 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
+ <PackageReference Include="CommandLineParser" Version="2.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
index c2f243fe0a..5683d164c6 100644
--- a/src/csharp/tests.json
+++ b/src/csharp/tests.json
@@ -23,8 +23,10 @@
"Grpc.Core.Tests.ClientServerTest",
"Grpc.Core.Tests.CompressionTest",
"Grpc.Core.Tests.ContextPropagationTest",
+ "Grpc.Core.Tests.ContextualMarshallerTest",
"Grpc.Core.Tests.GrpcEnvironmentTest",
"Grpc.Core.Tests.HalfcloseTest",
+ "Grpc.Core.Tests.MarshallerTest",
"Grpc.Core.Tests.MarshallingErrorsTest",
"Grpc.Core.Tests.MetadataTest",
"Grpc.Core.Tests.PerformanceTest",
diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec
index 704b35a29e..04e4d5768f 100644
--- a/src/objective-c/BoringSSL-GRPC.podspec
+++ b/src/objective-c/BoringSSL-GRPC.podspec
@@ -38,7 +38,7 @@
Pod::Spec.new do |s|
s.name = 'BoringSSL-GRPC'
- version = '0.0.1'
+ version = '0.0.2'
s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.'
# Adapted from the homepage:
@@ -81,7 +81,7 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '5.0'
s.osx.deployment_target = '10.7'
- name = 'openssl'
+ name = 'openssl_grpc'
# When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework.
# This lets users write their includes like `#include <openssl/ssl.h>` as opposed to `#include
@@ -1546,6 +1546,7 @@ Pod::Spec.new do |s|
sed -i'.back' '/^#define \\([A-Za-z0-9_]*\\) \\1/d' include/openssl/ssl.h
sed -i'.back' 'N;/^#define \\([A-Za-z0-9_]*\\) *\\\\\\n *\\1/d' include/openssl/ssl.h
sed -i'.back' 's/#ifndef md5_block_data_order/#ifndef GRPC_SHADOW_md5_block_data_order/g' crypto/fipsmodule/md5/md5.c
+ find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/;#include <openssl_grpc/;g'
END_OF_COMMAND
# Redefine symbols to avoid conflict when the same app also depends on OpenSSL. The list of
diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.h b/src/objective-c/GRPCClient/private/NSError+GRPC.h
index a63e76ee4d..fb05638b78 100644
--- a/src/objective-c/GRPCClient/private/NSError+GRPC.h
+++ b/src/objective-c/GRPCClient/private/NSError+GRPC.h
@@ -25,6 +25,6 @@
* and whose domain is |kGRPCErrorDomain|.
*/
+ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode
- details:(char *)details
+ details:(const char *)details
errorString:(const char *)errorString;
@end
diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m
index 199b2ebb6c..3eefed88d6 100644
--- a/src/objective-c/GRPCClient/private/NSError+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m
@@ -24,18 +24,20 @@ NSString *const kGRPCErrorDomain = @"io.grpc";
@implementation NSError (GRPC)
+ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode
- details:(char *)details
+ details:(const char *)details
errorString:(const char *)errorString {
if (statusCode == GRPC_STATUS_OK) {
return nil;
}
- NSString *message = [NSString stringWithCString:details encoding:NSUTF8StringEncoding];
- NSString *debugMessage = [NSString stringWithCString:errorString encoding:NSUTF8StringEncoding];
- return [NSError errorWithDomain:kGRPCErrorDomain
- code:statusCode
- userInfo:@{
- NSLocalizedDescriptionKey : message,
- NSDebugDescriptionErrorKey : debugMessage
- }];
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+ if (details) {
+ userInfo[NSLocalizedDescriptionKey] =
+ [NSString stringWithCString:details encoding:NSUTF8StringEncoding];
+ }
+ if (errorString) {
+ userInfo[NSDebugDescriptionErrorKey] =
+ [NSString stringWithCString:errorString encoding:NSUTF8StringEncoding];
+ }
+ return [NSError errorWithDomain:kGRPCErrorDomain code:statusCode userInfo:userInfo];
}
@end
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 75a669da4d..84893b92c1 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -39,7 +39,7 @@
#import "src/core/tsi/grpc_shadow_boringssl.h"
-#import <openssl/ssl.h>
+#import <openssl_grpc/ssl.h>
static void drain_cq(grpc_completion_queue *cq) {
grpc_event ev;
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 507d251b48..5d2f1340da 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -14,6 +14,7 @@ GRPC_LOCAL_SRC = '../../..'
InteropTestsLocalSSL
InteropTestsLocalCleartext
InteropTestsRemoteWithCronet
+ UnitTests
).each do |target_name|
target target_name do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true
diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
index 0e0e8babc0..f0d8123263 100644
--- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
+++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
@@ -13,6 +13,8 @@
16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */; };
20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */; };
333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; };
+ 5E0282E9215AA697007AC99D /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E0282E8215AA697007AC99D /* UnitTests.m */; };
+ 5E0282EB215AA697007AC99D /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm */; };
5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
5EAD6D271E27047400002378 /* CronetUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD6D261E27047400002378 /* CronetUnitTests.m */; };
@@ -54,10 +56,18 @@
91D4B3C85B6D8562F409CB48 /* libPods-InteropTestsLocalSSLCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */; };
BC111C80CBF7068B62869352 /* libPods-InteropTestsRemoteCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */; };
C3D6F4270A2FFF634D8849ED /* libPods-InteropTestsLocalCleartextCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */; };
+ CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */; };
F15EF7852DC70770EFDB1D2C /* libPods-AllTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 5E0282EC215AA697007AC99D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 635697C61B14FC11007A7283;
+ remoteInfo = Tests;
+ };
5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
@@ -138,6 +148,7 @@
1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.test.xcconfig"; sourceTree = "<group>"; };
17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = "<group>"; };
20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-UnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.test.xcconfig"; sourceTree = "<group>"; };
303F4A17EB1650FC44603D17 /* Pods-InteropTestsRemoteCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.release.xcconfig"; sourceTree = "<group>"; };
32748C4078AEB05F8F954361 /* Pods-InteropTestsRemoteCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.debug.xcconfig"; sourceTree = "<group>"; };
@@ -155,6 +166,9 @@
55B630C1FF8C36D1EFC4E0A4 /* Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig"; sourceTree = "<group>"; };
573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; sourceTree = "<group>"; };
5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.release.xcconfig"; sourceTree = "<group>"; };
+ 5E0282E6215AA697007AC99D /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5E0282E8215AA697007AC99D /* UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnitTests.m; sourceTree = "<group>"; };
+ 5E0282EA215AA697007AC99D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreCronetEnd2EndTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CoreCronetEnd2EndTests.mm; sourceTree = "<group>"; };
5EA908CF4CDA4CE218352A06 /* Pods-InteropTestsLocalSSLCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.release.xcconfig"; sourceTree = "<group>"; };
@@ -192,7 +206,9 @@
7BA53C6D224288D5870FE6F3 /* Pods-InteropTestsLocalCleartextCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; sourceTree = "<group>"; };
8B498B05C6DA0818B2FA91D4 /* Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; sourceTree = "<group>"; };
943138072A9605B5B8DC1FC0 /* Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; sourceTree = "<group>"; };
+ 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.test.xcconfig"; sourceTree = "<group>"; };
9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteWithCronet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.debug.xcconfig"; sourceTree = "<group>"; };
A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RxLibraryUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A6F832FCEFA6F6881E620F12 /* Pods-InteropTestsRemote.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.test.xcconfig"; sourceTree = "<group>"; };
AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = "<group>"; };
@@ -208,9 +224,11 @@
DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSL.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DC3CA1D948F068E76957A861 /* Pods-InteropTestsRemote.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.debug.xcconfig"; sourceTree = "<group>"; };
E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.debug.xcconfig"; sourceTree = "<group>"; };
+ E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.cronet.xcconfig"; sourceTree = "<group>"; };
E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = "<group>"; };
E4FD4606D4AB8D5A314D72F0 /* Pods-InteropTestsLocalCleartextCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; sourceTree = "<group>"; };
E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = "<group>"; };
+ EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = "<group>"; };
F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSLCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreCronetEnd2EndTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -219,6 +237,15 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 5E0282E3215AA697007AC99D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5E0282EB215AA697007AC99D /* libTests.a in Frameworks */,
+ CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
5E8A5DA11D3840B4000F8BC4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -341,6 +368,7 @@
F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */,
0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */,
F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */,
+ 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -394,10 +422,23 @@
41AA59529240A6BBBD3DB904 /* Pods-InteropTestsLocalSSLCFStream.test.xcconfig */,
55B630C1FF8C36D1EFC4E0A4 /* Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig */,
5EA908CF4CDA4CE218352A06 /* Pods-InteropTestsLocalSSLCFStream.release.xcconfig */,
+ A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */,
+ 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */,
+ E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */,
+ EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
+ 5E0282E7215AA697007AC99D /* UnitTests */ = {
+ isa = PBXGroup;
+ children = (
+ 5E0282E8215AA697007AC99D /* UnitTests.m */,
+ 5E0282EA215AA697007AC99D /* Info.plist */,
+ );
+ path = UnitTests;
+ sourceTree = "<group>";
+ };
5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = {
isa = PBXGroup;
children = (
@@ -432,6 +473,7 @@
5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */,
5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */,
5EAD6D251E27047400002378 /* CronetUnitTests */,
+ 5E0282E7215AA697007AC99D /* UnitTests */,
635697C81B14FC11007A7283 /* Products */,
51E4650F34F854F41FF053B3 /* Pods */,
136D535E19727099B941D7B1 /* Frameworks */,
@@ -453,6 +495,7 @@
5EC5E421208177CC000EF4AD /* InteropTestsRemoteCFStream.xctest */,
5EC5E4312081856B000EF4AD /* InteropTestsLocalCleartextCFStream.xctest */,
5EC5E442208185CE000EF4AD /* InteropTestsLocalSSLCFStream.xctest */,
+ 5E0282E6215AA697007AC99D /* UnitTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -485,6 +528,26 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
+ 5E0282E5215AA697007AC99D /* UnitTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 5E0282F2215AA697007AC99D /* Build configuration list for PBXNativeTarget "UnitTests" */;
+ buildPhases = (
+ F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */,
+ 5E0282E2215AA697007AC99D /* Sources */,
+ 5E0282E3215AA697007AC99D /* Frameworks */,
+ 5E0282E4215AA697007AC99D /* Resources */,
+ 9AD0B5E94F2AA5962EA6AA36 /* [CP] Copy Pods Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 5E0282ED215AA697007AC99D /* PBXTargetDependency */,
+ );
+ name = UnitTests;
+ productName = UnitTests;
+ productReference = 5E0282E6215AA697007AC99D /* UnitTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */;
@@ -729,6 +792,10 @@
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
+ 5E0282E5215AA697007AC99D = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ };
5E8A5DA31D3840B4000F8BC4 = {
CreatedOnToolsVersion = 7.3.1;
};
@@ -794,11 +861,19 @@
5EC5E420208177CC000EF4AD /* InteropTestsRemoteCFStream */,
5EC5E4302081856B000EF4AD /* InteropTestsLocalCleartextCFStream */,
5EC5E441208185CE000EF4AD /* InteropTestsLocalSSLCFStream */,
+ 5E0282E5215AA697007AC99D /* UnitTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ 5E0282E4215AA697007AC99D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
5E8A5DA21D3840B4000F8BC4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1098,6 +1173,24 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream-resources.sh\"\n";
showEnvVarsInLog = 0;
};
+ 9AD0B5E94F2AA5962EA6AA36 /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${SRCROOT}/Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests-resources.sh",
+ "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
A023FB55205A7EA37D413549 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -1260,6 +1353,24 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
+ F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-UnitTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
F3D5B2CDA172580341682830 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -1299,6 +1410,14 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 5E0282E2215AA697007AC99D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5E0282E9215AA697007AC99D /* UnitTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
5E8A5DA01D3840B4000F8BC4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1412,6 +1531,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
+ 5E0282ED215AA697007AC99D /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 635697C61B14FC11007A7283 /* Tests */;
+ targetProxy = 5E0282EC215AA697007AC99D /* PBXContainerItemProxy */;
+ };
5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 635697C61B14FC11007A7283 /* Tests */;
@@ -1455,6 +1579,128 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
+ 5E0282EE215AA697007AC99D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ INFOPLIST_FILE = UnitTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
+ };
+ name = Debug;
+ };
+ 5E0282EF215AA697007AC99D /* Test */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ INFOPLIST_FILE = UnitTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
+ };
+ name = Test;
+ };
+ 5E0282F0215AA697007AC99D /* Cronet */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ INFOPLIST_FILE = UnitTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
+ };
+ name = Cronet;
+ };
+ 5E0282F1215AA697007AC99D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ INFOPLIST_FILE = UnitTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
+ };
+ name = Release;
+ };
5E1228981E4D400F00E8504F /* Test */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -2602,6 +2848,17 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 5E0282F2215AA697007AC99D /* Build configuration list for PBXNativeTarget "UnitTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 5E0282EE215AA697007AC99D /* Debug */,
+ 5E0282EF215AA697007AC99D /* Test */,
+ 5E0282F0215AA697007AC99D /* Cronet */,
+ 5E0282F1215AA697007AC99D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme
new file mode 100644
index 0000000000..3af3555f48
--- /dev/null
+++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0920"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "NO"
+ buildForArchiving = "NO"
+ buildForAnalyzing = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E0282E5215AA697007AC99D"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E0282E5215AA697007AC99D"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E0282E5215AA697007AC99D"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5E0282E5215AA697007AC99D"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/src/objective-c/tests/UnitTests/Info.plist b/src/objective-c/tests/UnitTests/Info.plist
new file mode 100644
index 0000000000..6c40a6cd0c
--- /dev/null
+++ b/src/objective-c/tests/UnitTests/Info.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/src/objective-c/tests/UnitTests/UnitTests.m b/src/objective-c/tests/UnitTests/UnitTests.m
new file mode 100644
index 0000000000..57e686d1b6
--- /dev/null
+++ b/src/objective-c/tests/UnitTests/UnitTests.m
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#import <XCTest/XCTest.h>
+
+#import <GRPCClient/GRPCCall.h>
+
+#import "src/objective-c/GRPCClient/private/NSError+GRPC.h"
+
+@interface UnitTests : XCTestCase
+
+@end
+
+@implementation UnitTests
+
+- (void)testNSError {
+ const char *kDetails = "test details";
+ const char *kErrorString = "test errorString";
+ NSError *error1 = [NSError grpc_errorFromStatusCode:GRPC_STATUS_OK details:nil errorString:nil];
+ NSError *error2 = [NSError grpc_errorFromStatusCode:GRPC_STATUS_CANCELLED
+ details:kDetails
+ errorString:kErrorString];
+ NSError *error3 = [NSError grpc_errorFromStatusCode:GRPC_STATUS_UNAUTHENTICATED
+ details:kDetails
+ errorString:nil];
+ NSError *error4 =
+ [NSError grpc_errorFromStatusCode:GRPC_STATUS_UNAVAILABLE details:nil errorString:nil];
+
+ XCTAssertNil(error1);
+ XCTAssertEqual(error2.code, 1);
+ XCTAssertEqualObjects(error2.domain, @"io.grpc");
+ XCTAssertEqualObjects(error2.userInfo[NSLocalizedDescriptionKey],
+ [NSString stringWithUTF8String:kDetails]);
+ XCTAssertEqualObjects(error2.userInfo[NSDebugDescriptionErrorKey],
+ [NSString stringWithUTF8String:kErrorString]);
+ XCTAssertEqual(error3.code, 16);
+ XCTAssertEqualObjects(error3.domain, @"io.grpc");
+ XCTAssertEqualObjects(error3.userInfo[NSLocalizedDescriptionKey],
+ [NSString stringWithUTF8String:kDetails]);
+ XCTAssertNil(error3.userInfo[NSDebugDescriptionErrorKey]);
+ XCTAssertEqual(error4.code, 14);
+ XCTAssertEqualObjects(error4.domain, @"io.grpc");
+ XCTAssertNil(error4.userInfo[NSLocalizedDescriptionKey]);
+ XCTAssertNil(error4.userInfo[NSDebugDescriptionErrorKey]);
+}
+
+@end
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index 9dde07d55c..f37c6cf9f6 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -163,4 +163,14 @@ xcodebuild \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
+echo "TIME: $(date)"
+xcodebuild \
+ -workspace Tests.xcworkspace \
+ -scheme UnitTests \
+ -destination name="iPhone 8" \
+ test \
+ | egrep -v "$XCODEBUILD_FILTER" \
+ | egrep -v '^$' \
+ | egrep -v "(GPBDictionary|GPBArray)" -
+
exit 0
diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php
index 49b0e350f7..583c618d32 100644
--- a/src/php/tests/unit_tests/ChannelTest.php
+++ b/src/php/tests/unit_tests/ChannelTest.php
@@ -599,10 +599,10 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelForceNewOldChannelIdle2()
{
- $this->channel1 = new Grpc\Channel('localhost:50029', [
+ $this->channel1 = new Grpc\Channel('localhost:50032', [
"grpc_target_persist_bound" => 2,
]);
- $this->channel2 = new Grpc\Channel('localhost:50029', []);
+ $this->channel2 = new Grpc\Channel('localhost:50032', []);
// try to connect on channel2
$state = $this->channel1->getConnectivityState(true);
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 0f68e823d7..932621a38d 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -92,7 +92,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
- 'src/core/lib/iomgr/ev_epollsig_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
'src/core/lib/iomgr/ev_posix.cc',
'src/core/lib/iomgr/ev_windows.cc',
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 0c46f6c85a..1e7d7f687f 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -100,6 +100,7 @@ grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import;
grpc_channelz_get_servers_type grpc_channelz_get_servers_import;
grpc_channelz_get_channel_type grpc_channelz_get_channel_import;
grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import;
+grpc_channelz_get_socket_type grpc_channelz_get_socket_import;
grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import;
grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import;
grpc_use_signal_type grpc_use_signal_import;
@@ -356,6 +357,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_channelz_get_servers_import = (grpc_channelz_get_servers_type) GetProcAddress(library, "grpc_channelz_get_servers");
grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel");
grpc_channelz_get_subchannel_import = (grpc_channelz_get_subchannel_type) GetProcAddress(library, "grpc_channelz_get_subchannel");
+ grpc_channelz_get_socket_import = (grpc_channelz_get_socket_type) GetProcAddress(library, "grpc_channelz_get_socket");
grpc_insecure_channel_create_from_fd_import = (grpc_insecure_channel_create_from_fd_type) GetProcAddress(library, "grpc_insecure_channel_create_from_fd");
grpc_server_add_insecure_channel_from_fd_import = (grpc_server_add_insecure_channel_from_fd_type) GetProcAddress(library, "grpc_server_add_insecure_channel_from_fd");
grpc_use_signal_import = (grpc_use_signal_type) GetProcAddress(library, "grpc_use_signal");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index d00e75c326..ed4b6264b0 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -107,7 +107,7 @@ extern grpc_completion_queue_create_for_next_type grpc_completion_queue_create_f
typedef grpc_completion_queue*(*grpc_completion_queue_create_for_pluck_type)(void* reserved);
extern grpc_completion_queue_create_for_pluck_type grpc_completion_queue_create_for_pluck_import;
#define grpc_completion_queue_create_for_pluck grpc_completion_queue_create_for_pluck_import
-typedef grpc_completion_queue*(*grpc_completion_queue_create_for_callback_type)(void* shutdown_callback, void* reserved);
+typedef grpc_completion_queue*(*grpc_completion_queue_create_for_callback_type)(grpc_experimental_completion_queue_functor* shutdown_callback, void* reserved);
extern grpc_completion_queue_create_for_callback_type grpc_completion_queue_create_for_callback_import;
#define grpc_completion_queue_create_for_callback grpc_completion_queue_create_for_callback_import
typedef grpc_completion_queue*(*grpc_completion_queue_create_type)(const grpc_completion_queue_factory* factory, const grpc_completion_queue_attributes* attributes, void* reserved);
@@ -275,6 +275,9 @@ extern grpc_channelz_get_channel_type grpc_channelz_get_channel_import;
typedef char*(*grpc_channelz_get_subchannel_type)(intptr_t subchannel_id);
extern grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import;
#define grpc_channelz_get_subchannel grpc_channelz_get_subchannel_import
+typedef char*(*grpc_channelz_get_socket_type)(intptr_t socket_id);
+extern grpc_channelz_get_socket_type grpc_channelz_get_socket_import;
+#define grpc_channelz_get_socket grpc_channelz_get_socket_import
typedef grpc_channel*(*grpc_insecure_channel_create_from_fd_type)(const char* target, int fd, const grpc_channel_args* args);
extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import;
#define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import
@@ -407,10 +410,10 @@ extern grpc_call_set_credentials_type grpc_call_set_credentials_import;
typedef void(*grpc_server_credentials_set_auth_metadata_processor_type)(grpc_server_credentials* creds, grpc_auth_metadata_processor processor);
extern grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import;
#define grpc_server_credentials_set_auth_metadata_processor grpc_server_credentials_set_auth_metadata_processor_import
-typedef grpc_alts_credentials_options*(*grpc_alts_credentials_client_options_create_type)();
+typedef grpc_alts_credentials_options*(*grpc_alts_credentials_client_options_create_type)(void);
extern grpc_alts_credentials_client_options_create_type grpc_alts_credentials_client_options_create_import;
#define grpc_alts_credentials_client_options_create grpc_alts_credentials_client_options_create_import
-typedef grpc_alts_credentials_options*(*grpc_alts_credentials_server_options_create_type)();
+typedef grpc_alts_credentials_options*(*grpc_alts_credentials_server_options_create_type)(void);
extern grpc_alts_credentials_server_options_create_type grpc_alts_credentials_server_options_create_import;
#define grpc_alts_credentials_server_options_create grpc_alts_credentials_server_options_create_import
typedef void(*grpc_alts_credentials_client_options_add_target_service_account_type)(grpc_alts_credentials_options* options, const char* service_account);
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index cfed7ca12a..7710d34657 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -95,7 +95,7 @@ end
# creates a test stub that accesses host:port securely.
def create_stub(opts)
- address = "#{opts.host}:#{opts.port}"
+ address = "#{opts.server_host}:#{opts.server_port}"
# Provide channel args that request compression by default
# for compression interop tests
@@ -703,8 +703,8 @@ class NamedTests
end
# Args is used to hold the command line info.
-Args = Struct.new(:default_service_account, :host, :host_override,
- :oauth_scope, :port, :secure, :test_case,
+Args = Struct.new(:default_service_account, :server_host, :host_override,
+ :oauth_scope, :server_port, :secure, :test_case,
:use_test_ca)
# validates the command line options, returning them as a Hash.
@@ -715,7 +715,7 @@ def parse_args
opts.on('--oauth_scope scope',
'Scope for OAuth tokens') { |v| args['oauth_scope'] = v }
opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
- args['host'] = v
+ args['server_host'] = v
end
opts.on('--default_service_account email_address',
'email address of the default service account') do |v|
@@ -725,7 +725,9 @@ def parse_args
'override host via a HTTP header') do |v|
args['host_override'] = v
end
- opts.on('--server_port SERVER_PORT', 'server port') { |v| args['port'] = v }
+ opts.on('--server_port SERVER_PORT', 'server port') do |v|
+ args['server_port'] = v
+ end
# instance_methods(false) gives only the methods defined in that class
test_cases = NamedTests.instance_methods(false).map(&:to_s)
test_case_list = test_cases.join(',')
@@ -744,7 +746,7 @@ def parse_args
end
def _check_args(args)
- %w(host port test_case).each do |a|
+ %w(server_host server_port test_case).each do |a|
if args[a].nil?
fail(OptionParser::MissingArgument, "please specify --#{a}")
end
diff --git a/templates/README.md b/templates/README.md
index c837b5b260..a7aeec26c7 100644
--- a/templates/README.md
+++ b/templates/README.md
@@ -1,9 +1,13 @@
# Regenerating project files
-Prerequisites: `python`, `pip install mako`, `go`
+Prerequisites
+- `python`
+- `pip install mako` (the template processor)
+- `pip install pyyaml` (to read the yaml files)
+- `go` (required by boringssl dependency)
```
-# Regenerate the projects files using templates
+# Regenerate the projects files (and other generated files) using templates
tools/buildgen/generate_projects.sh
```
@@ -19,25 +23,13 @@ So instead we decided to work the following way:
targets and files needed to build grpc and its tests, as well as a basic system
for dependency description.
-* Each project file (Makefile, Visual Studio project files, Bazel's BUILD) is
-a [YAML](http://yaml.org) file used by the `build.yaml` file to generate the
-final output file.
+* Most of the build systems supported by gRPC (e.g. Makefile, cmake, XCode) have a template defined in this directory. The templates use the information from the `build.yaml` file to generate the project files specific to a given build system.
This way we can maintain as many project system as we see fit, without having
to manually maintain them when we add or remove new code to the repository.
Only the structure of the project file is relevant to the template. The actual
list of source code and targets isn't.
-We currently have template files for GNU Make, Visual Studio 2013,
-[Bazel](http://bazel.io) and [gyp](https://gyp.gsrc.io/) (albeit only for
-Node.js). In the future, we
-would like to expand to also generate [cmake](https://cmake.org)
-project files, XCode project files, and an Android.mk file allowing to compile
-gRPC using Android's NDK.
-
-We'll gladly accept contribution that'd create additional project files
-using that system.
-
# Structure of `build.yaml`
The `build.yaml` file has the following structure:
@@ -87,7 +79,6 @@ src: # list of files to compile
secure: boolean, # see below
baselib: boolean, # this is a low level library that has system
# dependencies
-vs_project_guid: '{...}', # Visual Studio's unique guid for that project
filegroups: # list of filegroups to merge to that project
# note that this will be expanded automatically
deps: # list of libraries this target depends on
@@ -95,12 +86,6 @@ deps_linkage: "..." # "static" or "dynamic". Used by the Makefile only to
# determine the way dependencies are linkned. Defaults
# to "dynamic".
dll: "..." # see below.
-dll_def: "..." # Visual Studio's dll definition file.
-vs_props: # List of property sheets to attach to that project.
-vs_config_type: "..." # DynamicLibrary/StaticLibrary. Used only when
- # creating a library. Specifies if we're building a
- # static library or a dll. Use in conjunction with `dll_def`.
-vs_packages: # List of nuget packages this project depends on.
```
## The `"build"` tag
@@ -137,23 +122,17 @@ protobuf is for `"c++"` ones.
## The `"dll"` tag
-Used only by Visual Studio's project files. "true" means the project will be
+Currently only used by cmake. "true" means the project will be
built with both static and dynamic runtimes. "false" means it'll only be built
with static runtime. "only" means it'll only be built with the dll runtime.
-## The `"dll_def"` tag
-
-Specifies the visual studio's dll definition file. When creating a DLL, you
-sometimes (not always) need a def file (see grpc.def).
-
# The template system
We're currently using the [mako templates](http://www.makotemplates.org/)
renderer. That choice enables us to simply render text files without dragging
with us a lot of other features. Feel free to explore the current templates
-in that directory. The simplest one is probably [BUILD.template](BUILD.template)
-which is used to create the [Bazel](http://bazel.io/) project file.
+in that directory.
## The renderer engine
diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template
index f912154301..98b6344a4b 100644
--- a/templates/gRPC-Core.podspec.template
+++ b/templates/gRPC-Core.podspec.template
@@ -174,7 +174,7 @@
ss.header_mappings_dir = '.'
ss.libraries = 'z'
ss.dependency "#{s.name}/Interface", version
- ss.dependency 'BoringSSL-GRPC', '0.0.1'
+ ss.dependency 'BoringSSL-GRPC', '0.0.2'
ss.dependency 'nanopb', '~> 0.3'
ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS'
@@ -223,5 +223,6 @@
s.prepare_command = <<-END_OF_COMMAND
find src/core/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
find src/core/ -type f -path '*.grpc_back' -print0 | xargs -0 rm
+ find src/core/ -type f \\( -path '*.h' -or -path '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/;#include <openssl_grpc/;g'
END_OF_COMMAND
end
diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template
index 986216fdbf..2b3bb8d97a 100644
--- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template
+++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template
@@ -43,7 +43,7 @@
Pod::Spec.new do |s|
s.name = 'BoringSSL-GRPC'
- version = '0.0.1'
+ version = '0.0.2'
s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.'
# Adapted from the homepage:
@@ -86,7 +86,7 @@
s.ios.deployment_target = '5.0'
s.osx.deployment_target = '10.7'
- name = 'openssl'
+ name = 'openssl_grpc'
# When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework.
# This lets users write their includes like `#include <openssl/ssl.h>` as opposed to `#include
@@ -1551,6 +1551,7 @@
sed -i'.back' '/^#define \\([A-Za-z0-9_]*\\) \\1/d' include/openssl/ssl.h
sed -i'.back' 'N;/^#define \\([A-Za-z0-9_]*\\) *\\\\\\n *\\1/d' include/openssl/ssl.h
sed -i'.back' 's/#ifndef md5_block_data_order/#ifndef GRPC_SHADOW_md5_block_data_order/g' crypto/fipsmodule/md5/md5.c
+ find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/;#include <openssl_grpc/;g'
END_OF_COMMAND
# Redefine symbols to avoid conflict when the same app also depends on OpenSSL. The list of
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index db2886d8e3..6d9ffcfb91 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -13,277 +13,347 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-POLLERS = ['epollex', 'epollsig', 'epoll1', 'poll', 'poll-cv']
-
-load("//bazel:grpc_build_system.bzl", "grpc_sh_test", "grpc_cc_binary", "grpc_cc_library")
-
"""Generates the appropriate build.json data for all the end2end tests."""
+load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library")
-def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True,
- name_resolution=True, secure=True, tracing=False,
- platforms=['windows', 'linux', 'mac', 'posix'],
- is_inproc=False, is_http2=True, supports_proxy_auth=False,
- supports_write_buffering=True, client_channel=True):
- return struct(
- fullstack=fullstack,
- includes_proxy=includes_proxy,
- dns_resolver=dns_resolver,
- name_resolution=name_resolution,
- secure=secure,
- tracing=tracing,
- is_inproc=is_inproc,
- is_http2=is_http2,
- supports_proxy_auth=supports_proxy_auth,
- supports_write_buffering=supports_write_buffering,
- client_channel=client_channel,
- #platforms=platforms,
- )
+POLLERS = ["epollex", "epoll1", "poll", "poll-cv"]
+def _fixture_options(
+ fullstack = True,
+ includes_proxy = False,
+ dns_resolver = True,
+ name_resolution = True,
+ secure = True,
+ tracing = False,
+ _platforms = ["windows", "linux", "mac", "posix"],
+ is_inproc = False,
+ is_http2 = True,
+ supports_proxy_auth = False,
+ supports_write_buffering = True,
+ client_channel = True):
+ return struct(
+ fullstack = fullstack,
+ includes_proxy = includes_proxy,
+ dns_resolver = dns_resolver,
+ name_resolution = name_resolution,
+ secure = secure,
+ tracing = tracing,
+ is_inproc = is_inproc,
+ is_http2 = is_http2,
+ supports_proxy_auth = supports_proxy_auth,
+ supports_write_buffering = supports_write_buffering,
+ client_channel = client_channel,
+ #_platforms=_platforms,
+ )
# maps fixture name to whether it requires the security library
END2END_FIXTURES = {
- 'h2_compress': fixture_options(),
- 'h2_census': fixture_options(),
+ "h2_compress": _fixture_options(),
+ "h2_census": _fixture_options(),
# TODO(juanlishen): This is disabled for now, but should be considered to re-enable once we have
# decided how the load reporting service should be enabled.
- #'h2_load_reporting': fixture_options(),
- 'h2_fakesec': fixture_options(),
- 'h2_fd': fixture_options(dns_resolver=False, fullstack=False,
- client_channel=False,
- platforms=['linux', 'mac', 'posix']),
- 'h2_full': fixture_options(),
- 'h2_full+pipe': fixture_options(platforms=['linux']),
- 'h2_full+trace': fixture_options(tracing=True),
- 'h2_full+workarounds': fixture_options(),
- 'h2_http_proxy': fixture_options(supports_proxy_auth=True),
- 'h2_oauth2': fixture_options(),
- 'h2_proxy': fixture_options(includes_proxy=True),
- 'h2_sockpair_1byte': fixture_options(fullstack=False, dns_resolver=False,
- client_channel=False),
- 'h2_sockpair': fixture_options(fullstack=False, dns_resolver=False,
- client_channel=False),
- 'h2_sockpair+trace': fixture_options(fullstack=False, dns_resolver=False,
- tracing=True, client_channel=False),
- 'h2_ssl': fixture_options(secure=True),
- 'h2_local': fixture_options(secure=True, dns_resolver=False, platforms=['linux', 'mac', 'posix']),
- 'h2_ssl_proxy': fixture_options(includes_proxy=True, secure=True),
- 'h2_uds': fixture_options(dns_resolver=False,
- platforms=['linux', 'mac', 'posix']),
- 'inproc': fixture_options(fullstack=False, dns_resolver=False,
- name_resolution=False, is_inproc=True,
- is_http2=False, supports_write_buffering=False,
- client_channel=False),
+ #'h2_load_reporting': _fixture_options(),
+ "h2_fakesec": _fixture_options(),
+ "h2_fd": _fixture_options(
+ dns_resolver = False,
+ fullstack = False,
+ client_channel = False,
+ _platforms = ["linux", "mac", "posix"],
+ ),
+ "h2_full": _fixture_options(),
+ "h2_full+pipe": _fixture_options(_platforms = ["linux"]),
+ "h2_full+trace": _fixture_options(tracing = True),
+ "h2_full+workarounds": _fixture_options(),
+ "h2_http_proxy": _fixture_options(supports_proxy_auth = True),
+ "h2_oauth2": _fixture_options(),
+ "h2_proxy": _fixture_options(includes_proxy = True),
+ "h2_sockpair_1byte": _fixture_options(
+ fullstack = False,
+ dns_resolver = False,
+ client_channel = False,
+ ),
+ "h2_sockpair": _fixture_options(
+ fullstack = False,
+ dns_resolver = False,
+ client_channel = False,
+ ),
+ "h2_sockpair+trace": _fixture_options(
+ fullstack = False,
+ dns_resolver = False,
+ tracing = True,
+ client_channel = False,
+ ),
+ "h2_ssl": _fixture_options(secure = True),
+ "h2_local": _fixture_options(secure = True, dns_resolver = False, _platforms = ["linux", "mac", "posix"]),
+ "h2_ssl_proxy": _fixture_options(includes_proxy = True, secure = True),
+ "h2_uds": _fixture_options(
+ dns_resolver = False,
+ _platforms = ["linux", "mac", "posix"],
+ ),
+ "inproc": _fixture_options(
+ fullstack = False,
+ dns_resolver = False,
+ name_resolution = False,
+ is_inproc = True,
+ is_http2 = False,
+ supports_write_buffering = False,
+ client_channel = False,
+ ),
}
-
-def test_options(needs_fullstack=False, needs_dns=False, needs_names=False,
- proxyable=True, secure=False, traceable=False,
- exclude_inproc=False, needs_http2=False,
- needs_proxy_auth=False, needs_write_buffering=False,
- needs_client_channel=False):
- return struct(
- needs_fullstack=needs_fullstack,
- needs_dns=needs_dns,
- needs_names=needs_names,
- proxyable=proxyable,
- secure=secure,
- traceable=traceable,
- exclude_inproc=exclude_inproc,
- needs_http2=needs_http2,
- needs_proxy_auth=needs_proxy_auth,
- needs_write_buffering=needs_write_buffering,
- needs_client_channel=needs_client_channel,
- )
-
+def _test_options(
+ needs_fullstack = False,
+ needs_dns = False,
+ needs_names = False,
+ proxyable = True,
+ secure = False,
+ traceable = False,
+ exclude_inproc = False,
+ needs_http2 = False,
+ needs_proxy_auth = False,
+ needs_write_buffering = False,
+ needs_client_channel = False):
+ return struct(
+ needs_fullstack = needs_fullstack,
+ needs_dns = needs_dns,
+ needs_names = needs_names,
+ proxyable = proxyable,
+ secure = secure,
+ traceable = traceable,
+ exclude_inproc = exclude_inproc,
+ needs_http2 = needs_http2,
+ needs_proxy_auth = needs_proxy_auth,
+ needs_write_buffering = needs_write_buffering,
+ needs_client_channel = needs_client_channel,
+ )
# maps test names to options
END2END_TESTS = {
- 'bad_hostname': test_options(needs_names=True),
- 'bad_ping': test_options(needs_fullstack=True,proxyable=False),
- 'binary_metadata': test_options(),
- 'resource_quota_server': test_options(proxyable=False),
- 'call_creds': test_options(secure=True),
- 'call_host_override': test_options(needs_fullstack=True, needs_dns=True,
- needs_names=True),
- 'cancel_after_accept': test_options(),
- 'cancel_after_client_done': test_options(),
- 'cancel_after_invoke': test_options(),
- 'cancel_after_round_trip': test_options(),
- 'cancel_before_invoke': test_options(),
- 'cancel_in_a_vacuum': test_options(),
- 'cancel_with_status': test_options(),
- 'compressed_payload': test_options(proxyable=False, exclude_inproc=True),
- 'connectivity': test_options(needs_fullstack=True, needs_names=True,
- proxyable=False),
- 'channelz': test_options(),
- 'default_host': test_options(needs_fullstack=True, needs_dns=True,
- needs_names=True),
- 'disappearing_server': test_options(needs_fullstack=True,needs_names=True),
- 'empty_batch': test_options(),
- 'filter_causes_close': test_options(),
- 'filter_call_init_fails': test_options(),
- 'graceful_server_shutdown': test_options(exclude_inproc=True),
- 'hpack_size': test_options(proxyable=False, traceable=False,
- exclude_inproc=True),
- 'high_initial_seqno': test_options(),
- 'idempotent_request': test_options(),
- 'invoke_large_request': test_options(),
- 'keepalive_timeout': test_options(proxyable=False, needs_http2=True),
- 'large_metadata': test_options(),
- 'max_concurrent_streams': test_options(proxyable=False,
- exclude_inproc=True),
- 'max_connection_age': test_options(exclude_inproc=True),
- 'max_connection_idle': test_options(needs_fullstack=True, proxyable=False),
- 'max_message_length': test_options(),
- 'negative_deadline': test_options(),
- 'network_status_change': test_options(),
- 'no_error_on_hotpath': test_options(proxyable=False),
- 'no_logging': test_options(traceable=False),
- 'no_op': test_options(),
- 'payload': test_options(),
+ "bad_hostname": _test_options(needs_names = True),
+ "bad_ping": _test_options(needs_fullstack = True, proxyable = False),
+ "binary_metadata": _test_options(),
+ "resource_quota_server": _test_options(proxyable = False),
+ "call_creds": _test_options(secure = True),
+ "call_host_override": _test_options(
+ needs_fullstack = True,
+ needs_dns = True,
+ needs_names = True,
+ ),
+ "cancel_after_accept": _test_options(),
+ "cancel_after_client_done": _test_options(),
+ "cancel_after_invoke": _test_options(),
+ "cancel_after_round_trip": _test_options(),
+ "cancel_before_invoke": _test_options(),
+ "cancel_in_a_vacuum": _test_options(),
+ "cancel_with_status": _test_options(),
+ "compressed_payload": _test_options(proxyable = False, exclude_inproc = True),
+ "connectivity": _test_options(
+ needs_fullstack = True,
+ needs_names = True,
+ proxyable = False,
+ ),
+ "channelz": _test_options(),
+ "default_host": _test_options(
+ needs_fullstack = True,
+ needs_dns = True,
+ needs_names = True,
+ ),
+ "disappearing_server": _test_options(needs_fullstack = True, needs_names = True),
+ "empty_batch": _test_options(),
+ "filter_causes_close": _test_options(),
+ "filter_call_init_fails": _test_options(),
+ "graceful_server_shutdown": _test_options(exclude_inproc = True),
+ "hpack_size": _test_options(
+ proxyable = False,
+ traceable = False,
+ exclude_inproc = True,
+ ),
+ "high_initial_seqno": _test_options(),
+ "idempotent_request": _test_options(),
+ "invoke_large_request": _test_options(),
+ "keepalive_timeout": _test_options(proxyable = False, needs_http2 = True),
+ "large_metadata": _test_options(),
+ "max_concurrent_streams": _test_options(
+ proxyable = False,
+ exclude_inproc = True,
+ ),
+ "max_connection_age": _test_options(exclude_inproc = True),
+ "max_connection_idle": _test_options(needs_fullstack = True, proxyable = False),
+ "max_message_length": _test_options(),
+ "negative_deadline": _test_options(),
+ "network_status_change": _test_options(),
+ "no_error_on_hotpath": _test_options(proxyable = False),
+ "no_logging": _test_options(traceable = False),
+ "no_op": _test_options(),
+ "payload": _test_options(),
# TODO(juanlishen): This is disabled for now because it depends on some generated functions in
# end2end_tests.cc, which are not generated because they would depend on OpenCensus while
# OpenCensus can only be built via Bazel so far.
- # 'load_reporting_hook': test_options(),
- 'ping_pong_streaming': test_options(),
- 'ping': test_options(needs_fullstack=True, proxyable=False),
- 'proxy_auth': test_options(needs_proxy_auth=True),
- 'registered_call': test_options(),
- 'request_with_flags': test_options(proxyable=False),
- 'request_with_payload': test_options(),
+ # 'load_reporting_hook': _test_options(),
+ "ping_pong_streaming": _test_options(),
+ "ping": _test_options(needs_fullstack = True, proxyable = False),
+ "proxy_auth": _test_options(needs_proxy_auth = True),
+ "registered_call": _test_options(),
+ "request_with_flags": _test_options(proxyable = False),
+ "request_with_payload": _test_options(),
# TODO(roth): Remove proxyable=False for all retry tests once we
# have a way for the proxy to propagate the fact that trailing
# metadata is available when initial metadata is returned.
# See https://github.com/grpc/grpc/issues/14467 for context.
- 'retry': test_options(needs_client_channel=True, proxyable=False),
- 'retry_cancellation': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_disabled': test_options(needs_client_channel=True, proxyable=False),
- 'retry_exceeds_buffer_size_in_initial_batch': test_options(
- needs_client_channel=True, proxyable=False),
- 'retry_exceeds_buffer_size_in_subsequent_batch': test_options(
- needs_client_channel=True, proxyable=False),
- 'retry_non_retriable_status': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_non_retriable_status_before_recv_trailing_metadata_started':
- test_options(needs_client_channel=True, proxyable=False),
- 'retry_recv_initial_metadata': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_recv_message': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_server_pushback_delay': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_server_pushback_disabled': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_streaming': test_options(needs_client_channel=True, proxyable=False),
- 'retry_streaming_after_commit': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_streaming_succeeds_before_replay_finished': test_options(
- needs_client_channel=True, proxyable=False),
- 'retry_throttled': test_options(needs_client_channel=True,
- proxyable=False),
- 'retry_too_many_attempts': test_options(needs_client_channel=True,
- proxyable=False),
- 'server_finishes_request': test_options(),
- 'shutdown_finishes_calls': test_options(),
- 'shutdown_finishes_tags': test_options(),
- 'simple_cacheable_request': test_options(),
- 'simple_delayed_request': test_options(needs_fullstack=True),
- 'simple_metadata': test_options(),
- 'simple_request': test_options(),
- 'streaming_error_response': test_options(),
- 'stream_compression_compressed_payload': test_options(proxyable=False,
- exclude_inproc=True),
- 'stream_compression_payload': test_options(exclude_inproc=True),
- 'stream_compression_ping_pong_streaming': test_options(exclude_inproc=True),
- 'trailing_metadata': test_options(),
- 'authority_not_supported': test_options(),
- 'filter_latency': test_options(),
- 'filter_status_code': test_options(),
- 'workaround_cronet_compression': test_options(),
- 'write_buffering': test_options(needs_write_buffering=True),
- 'write_buffering_at_end': test_options(needs_write_buffering=True),
+ "retry": _test_options(needs_client_channel = True, proxyable = False),
+ "retry_cancellation": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_disabled": _test_options(needs_client_channel = True, proxyable = False),
+ "retry_exceeds_buffer_size_in_initial_batch": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_exceeds_buffer_size_in_subsequent_batch": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_non_retriable_status": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_non_retriable_status_before_recv_trailing_metadata_started": _test_options(needs_client_channel = True, proxyable = False),
+ "retry_recv_initial_metadata": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_recv_message": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_server_pushback_delay": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_server_pushback_disabled": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_streaming": _test_options(needs_client_channel = True, proxyable = False),
+ "retry_streaming_after_commit": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_streaming_succeeds_before_replay_finished": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_throttled": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "retry_too_many_attempts": _test_options(
+ needs_client_channel = True,
+ proxyable = False,
+ ),
+ "server_finishes_request": _test_options(),
+ "shutdown_finishes_calls": _test_options(),
+ "shutdown_finishes_tags": _test_options(),
+ "simple_cacheable_request": _test_options(),
+ "simple_delayed_request": _test_options(needs_fullstack = True),
+ "simple_metadata": _test_options(),
+ "simple_request": _test_options(),
+ "streaming_error_response": _test_options(),
+ "stream_compression_compressed_payload": _test_options(
+ proxyable = False,
+ exclude_inproc = True,
+ ),
+ "stream_compression_payload": _test_options(exclude_inproc = True),
+ "stream_compression_ping_pong_streaming": _test_options(exclude_inproc = True),
+ "trailing_metadata": _test_options(),
+ "authority_not_supported": _test_options(),
+ "filter_latency": _test_options(),
+ "filter_status_code": _test_options(),
+ "workaround_cronet_compression": _test_options(),
+ "write_buffering": _test_options(needs_write_buffering = True),
+ "write_buffering_at_end": _test_options(needs_write_buffering = True),
}
-
-def compatible(fopt, topt):
- if topt.needs_fullstack:
- if not fopt.fullstack:
- return False
- if topt.needs_dns:
- if not fopt.dns_resolver:
- return False
- if topt.needs_names:
- if not fopt.name_resolution:
- return False
- if not topt.proxyable:
- if fopt.includes_proxy:
- return False
- if not topt.traceable:
- if fopt.tracing:
- return False
- if topt.exclude_inproc:
- if fopt.is_inproc:
- return False
- if topt.needs_http2:
- if not fopt.is_http2:
- return False
- if topt.needs_proxy_auth:
- if not fopt.supports_proxy_auth:
- return False
- if topt.needs_write_buffering:
- if not fopt.supports_write_buffering:
- return False
- if topt.needs_client_channel:
- if not fopt.client_channel:
- return False
- return True
-
+def _compatible(fopt, topt):
+ if topt.needs_fullstack:
+ if not fopt.fullstack:
+ return False
+ if topt.needs_dns:
+ if not fopt.dns_resolver:
+ return False
+ if topt.needs_names:
+ if not fopt.name_resolution:
+ return False
+ if not topt.proxyable:
+ if fopt.includes_proxy:
+ return False
+ if not topt.traceable:
+ if fopt.tracing:
+ return False
+ if topt.exclude_inproc:
+ if fopt.is_inproc:
+ return False
+ if topt.needs_http2:
+ if not fopt.is_http2:
+ return False
+ if topt.needs_proxy_auth:
+ if not fopt.supports_proxy_auth:
+ return False
+ if topt.needs_write_buffering:
+ if not fopt.supports_write_buffering:
+ return False
+ if topt.needs_client_channel:
+ if not fopt.client_channel:
+ return False
+ return True
def grpc_end2end_tests():
- grpc_cc_library(
- name = 'end2end_tests',
- srcs = ['end2end_tests.cc', 'end2end_test_utils.cc'] + [
- 'tests/%s.cc' % t
- for t in sorted(END2END_TESTS.keys())],
- hdrs = [
- 'tests/cancel_test_helpers.h',
- 'end2end_tests.h'
- ],
- language = "C++",
- deps = [
- ':cq_verifier',
- ':ssl_test_data',
- ':http_proxy',
- ':proxy',
- ]
- )
-
- for f, fopt in END2END_FIXTURES.items():
- grpc_cc_binary(
- name = '%s_test' % f,
- srcs = ['fixtures/%s.cc' % f],
- language = "C++",
- deps = [
- ':end2end_tests',
- '//test/core/util:grpc_test_util',
- '//:grpc',
- '//test/core/util:gpr_test_util',
- '//:gpr',
- ],
+ grpc_cc_library(
+ name = "end2end_tests",
+ srcs = ["end2end_tests.cc", "end2end_test_utils.cc"] + [
+ "tests/%s.cc" % t
+ for t in sorted(END2END_TESTS.keys())
+ ],
+ hdrs = [
+ "tests/cancel_test_helpers.h",
+ "end2end_tests.h",
+ ],
+ language = "C++",
+ deps = [
+ ":cq_verifier",
+ ":ssl_test_data",
+ ":http_proxy",
+ ":proxy",
+ ],
)
- for t, topt in END2END_TESTS.items():
- #print(compatible(fopt, topt), f, t, fopt, topt)
- if not compatible(fopt, topt): continue
- for poller in POLLERS:
- native.sh_test(
- name = '%s_test@%s@poller=%s' % (f, t, poller),
- data = [':%s_test' % f],
- srcs = ['end2end_test.sh'],
- args = [
- '$(location %s_test)' % f,
- t,
- poller,
- ],
+
+ for f, fopt in END2END_FIXTURES.items():
+ grpc_cc_binary(
+ name = "%s_test" % f,
+ srcs = ["fixtures/%s.cc" % f],
+ language = "C++",
+ deps = [
+ ":end2end_tests",
+ "//test/core/util:grpc_test_util",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//:gpr",
+ ],
)
+ for t, topt in END2END_TESTS.items():
+ #print(_compatible(fopt, topt), f, t, fopt, topt)
+ if not _compatible(fopt, topt):
+ continue
+ for poller in POLLERS:
+ native.sh_test(
+ name = "%s_test@%s@poller=%s" % (f, t, poller),
+ data = [":%s_test" % f],
+ srcs = ["end2end_test.sh"],
+ args = [
+ "$(location %s_test)" % f,
+ t,
+ poller,
+ ],
+ )
diff --git a/test/core/end2end/inproc_callback_test.cc b/test/core/end2end/inproc_callback_test.cc
index 0d6c7c75a8..310030046a 100644
--- a/test/core/end2end/inproc_callback_test.cc
+++ b/test/core/end2end/inproc_callback_test.cc
@@ -37,13 +37,16 @@ typedef struct inproc_fixture_data {
namespace {
template <typename F>
-class CQDeletingCallback : public grpc_core::CQCallbackInterface {
+class CQDeletingCallback : public grpc_experimental_completion_queue_functor {
public:
- explicit CQDeletingCallback(F f) : func_(f) {}
- ~CQDeletingCallback() override {}
- void Run(bool ok) override {
- func_(ok);
- grpc_core::Delete(this);
+ explicit CQDeletingCallback(F f) : func_(f) {
+ functor_run = &CQDeletingCallback::Run;
+ }
+ ~CQDeletingCallback() {}
+ static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
+ auto* callback = static_cast<CQDeletingCallback*>(cb);
+ callback->func_(static_cast<bool>(ok));
+ grpc_core::Delete(callback);
}
private:
@@ -51,18 +54,24 @@ class CQDeletingCallback : public grpc_core::CQCallbackInterface {
};
template <typename F>
-grpc_core::CQCallbackInterface* NewDeletingCallback(F f) {
+grpc_experimental_completion_queue_functor* NewDeletingCallback(F f) {
return grpc_core::New<CQDeletingCallback<F>>(f);
}
-class ShutdownCallback : public grpc_core::CQCallbackInterface {
+class ShutdownCallback : public grpc_experimental_completion_queue_functor {
public:
ShutdownCallback() : done_(false) {
+ functor_run = &ShutdownCallback::StaticRun;
gpr_mu_init(&mu_);
gpr_cv_init(&cv_);
}
- ~ShutdownCallback() override {}
- void Run(bool ok) override {
+ ~ShutdownCallback() {}
+ static void StaticRun(grpc_experimental_completion_queue_functor* cb,
+ int ok) {
+ auto* callback = static_cast<ShutdownCallback*>(cb);
+ callback->Run(static_cast<bool>(ok));
+ }
+ void Run(bool ok) {
gpr_log(GPR_DEBUG, "CQ shutdown notification invoked");
gpr_mu_lock(&mu_);
done_ = true;
@@ -170,7 +179,7 @@ static void verify_tags(gpr_timespec deadline) {
// This function creates a callback functor that emits the
// desired tag into the global tag set
-static grpc_core::CQCallbackInterface* tag(intptr_t t) {
+static grpc_experimental_completion_queue_functor* tag(intptr_t t) {
auto func = [t](bool ok) {
gpr_mu_lock(&tags_mu);
gpr_log(GPR_DEBUG, "Completing operation %" PRIdPTR, t);
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
index 7754bc4970..70ee83acd2 100644
--- a/test/core/iomgr/BUILD
+++ b/test/core/iomgr/BUILD
@@ -40,6 +40,7 @@ grpc_cc_library(
grpc_cc_test(
name = "combiner_test",
srcs = ["combiner_test.cc"],
+ data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"],
language = "C++",
deps = [
"//:gpr",
@@ -47,7 +48,6 @@ grpc_cc_test(
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
- data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"],
)
grpc_cc_test(
@@ -89,18 +89,6 @@ grpc_cc_test(
)
grpc_cc_test(
- name = "ev_epollsig_linux_test",
- srcs = ["ev_epollsig_linux_test.cc"],
- language = "C++",
- deps = [
- "//:gpr",
- "//:grpc",
- "//test/core/util:gpr_test_util",
- "//test/core/util:grpc_test_util",
- ],
-)
-
-grpc_cc_test(
name = "fd_conservation_posix_test",
srcs = ["fd_conservation_posix_test.cc"],
language = "C++",
@@ -136,7 +124,6 @@ grpc_cc_test(
],
)
-
grpc_cc_test(
name = "load_file_test",
srcs = ["load_file_test.cc"],
@@ -150,18 +137,6 @@ grpc_cc_test(
)
grpc_cc_test(
- name = "pollset_set_test",
- srcs = ["pollset_set_test.cc"],
- language = "C++",
- deps = [
- "//:gpr",
- "//:grpc",
- "//test/core/util:gpr_test_util",
- "//test/core/util:grpc_test_util",
- ],
-)
-
-grpc_cc_test(
name = "resolve_address_posix_test",
srcs = ["resolve_address_posix_test.cc"],
language = "C++",
@@ -176,10 +151,10 @@ grpc_cc_test(
grpc_cc_test(
name = "resolve_address_using_ares_resolver_test",
srcs = ["resolve_address_test.cc"],
- language = "C++",
args = [
"--resolver=ares",
],
+ language = "C++",
deps = [
"//:gpr",
"//:grpc",
@@ -191,10 +166,10 @@ grpc_cc_test(
grpc_cc_test(
name = "resolve_address_using_native_resolver_test",
srcs = ["resolve_address_test.cc"],
- language = "C++",
args = [
"--resolver=native",
],
+ language = "C++",
deps = [
"//:gpr",
"//:grpc",
@@ -276,7 +251,6 @@ grpc_cc_test(
],
)
-
grpc_cc_test(
name = "tcp_server_posix_test",
srcs = ["tcp_server_posix_test.cc"],
diff --git a/test/core/iomgr/ev_epollsig_linux_test.cc b/test/core/iomgr/ev_epollsig_linux_test.cc
deleted file mode 100644
index 28c9dd408c..0000000000
--- a/test/core/iomgr/ev_epollsig_linux_test.cc
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- *
- * Copyright 2015 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 "src/core/lib/iomgr/port.h"
-
-/* This test only relevant on linux systems where epoll() is available */
-#ifdef GRPC_LINUX_EPOLL_CREATE1
-#include "src/core/lib/iomgr/ev_epollsig_linux.h"
-#include "src/core/lib/iomgr/ev_posix.h"
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/gprpp/thd.h"
-#include "src/core/lib/iomgr/iomgr.h"
-#include "test/core/util/test_config.h"
-
-typedef struct test_pollset {
- grpc_pollset* pollset;
- gpr_mu* mu;
-} test_pollset;
-
-typedef struct test_fd {
- int inner_fd;
- grpc_fd* fd;
-} test_fd;
-
-/* num_fds should be an even number */
-static void test_fd_init(test_fd* tfds, int* fds, int num_fds) {
- int i;
- int r;
-
- /* Create some dummy file descriptors. Currently using pipe file descriptors
- * for this test but we could use any other type of file descriptors. Also,
- * since pipe() used in this test creates two fds in each call, num_fds should
- * be an even number */
- GPR_ASSERT((num_fds % 2) == 0);
- for (i = 0; i < num_fds; i = i + 2) {
- r = pipe(fds + i);
- if (r != 0) {
- gpr_log(GPR_ERROR, "Error in creating pipe. %d (%s)", errno,
- strerror(errno));
- return;
- }
- }
-
- for (i = 0; i < num_fds; i++) {
- tfds[i].inner_fd = fds[i];
- tfds[i].fd = grpc_fd_create(fds[i], "test_fd", false);
- }
-}
-
-static void test_fd_cleanup(test_fd* tfds, int num_fds) {
- int release_fd;
- int i;
-
- for (i = 0; i < num_fds; i++) {
- grpc_fd_shutdown(tfds[i].fd,
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_fd_cleanup"));
- grpc_core::ExecCtx::Get()->Flush();
-
- grpc_fd_orphan(tfds[i].fd, nullptr, &release_fd, "test_fd_cleanup");
- grpc_core::ExecCtx::Get()->Flush();
-
- GPR_ASSERT(release_fd == tfds[i].inner_fd);
- close(tfds[i].inner_fd);
- }
-}
-
-static void test_pollset_init(test_pollset* pollsets, int num_pollsets) {
- int i;
- for (i = 0; i < num_pollsets; i++) {
- pollsets[i].pollset =
- static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
- grpc_pollset_init(pollsets[i].pollset, &pollsets[i].mu);
- }
-}
-
-static void destroy_pollset(void* p, grpc_error* error) {
- grpc_pollset_destroy(static_cast<grpc_pollset*>(p));
-}
-
-static void test_pollset_cleanup(test_pollset* pollsets, int num_pollsets) {
- grpc_closure destroyed;
- int i;
-
- for (i = 0; i < num_pollsets; i++) {
- GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, pollsets[i].pollset,
- grpc_schedule_on_exec_ctx);
- grpc_pollset_shutdown(pollsets[i].pollset, &destroyed);
-
- grpc_core::ExecCtx::Get()->Flush();
- gpr_free(pollsets[i].pollset);
- }
-}
-
- /*
- * Cases to test:
- * case 1) Polling islands of both fd and pollset are NULL
- * case 2) Polling island of fd is NULL but that of pollset is not-NULL
- * case 3) Polling island of fd is not-NULL but that of pollset is NULL
- * case 4) Polling islands of both fd and pollset are not-NULL and:
- * case 4.1) Polling islands of fd and pollset are equal
- * case 4.2) Polling islands of fd and pollset are NOT-equal (This results
- * in a merge)
- * */
-
-#define NUM_FDS 8
-#define NUM_POLLSETS 4
-
-static void test_add_fd_to_pollset() {
- grpc_core::ExecCtx exec_ctx;
- test_fd tfds[NUM_FDS];
- int fds[NUM_FDS];
- test_pollset pollsets[NUM_POLLSETS];
- void* expected_pi = nullptr;
- int i;
-
- test_fd_init(tfds, fds, NUM_FDS);
- test_pollset_init(pollsets, NUM_POLLSETS);
-
- /*Step 1.
- * Create three polling islands (This will exercise test case 1 and 2) with
- * the following configuration:
- * polling island 0 = { fds:0,1,2, pollsets:0}
- * polling island 1 = { fds:3,4, pollsets:1}
- * polling island 2 = { fds:5,6,7 pollsets:2}
- *
- *Step 2.
- * Add pollset 3 to polling island 0 (by adding fds 0 and 1 to pollset 3)
- * (This will exercise test cases 3 and 4.1). The configuration becomes:
- * polling island 0 = { fds:0,1,2, pollsets:0,3} <<< pollset 3 added here
- * polling island 1 = { fds:3,4, pollsets:1}
- * polling island 2 = { fds:5,6,7 pollsets:2}
- *
- *Step 3.
- * Merge polling islands 0 and 1 by adding fd 0 to pollset 1 (This will
- * exercise test case 4.2). The configuration becomes:
- * polling island (merged) = {fds: 0,1,2,3,4, pollsets: 0,1,3}
- * polling island 2 = {fds: 5,6,7 pollsets: 2}
- *
- *Step 4.
- * Finally do one more merge by adding fd 3 to pollset 2.
- * polling island (merged) = {fds: 0,1,2,3,4,5,6,7, pollsets: 0,1,2,3}
- */
-
- /* == Step 1 == */
- for (i = 0; i <= 2; i++) {
- grpc_pollset_add_fd(pollsets[0].pollset, tfds[i].fd);
- grpc_core::ExecCtx::Get()->Flush();
- }
-
- for (i = 3; i <= 4; i++) {
- grpc_pollset_add_fd(pollsets[1].pollset, tfds[i].fd);
- grpc_core::ExecCtx::Get()->Flush();
- }
-
- for (i = 5; i <= 7; i++) {
- grpc_pollset_add_fd(pollsets[2].pollset, tfds[i].fd);
- grpc_core::ExecCtx::Get()->Flush();
- }
-
- /* == Step 2 == */
- for (i = 0; i <= 1; i++) {
- grpc_pollset_add_fd(pollsets[3].pollset, tfds[i].fd);
- grpc_core::ExecCtx::Get()->Flush();
- }
-
- /* == Step 3 == */
- grpc_pollset_add_fd(pollsets[1].pollset, tfds[0].fd);
- grpc_core::ExecCtx::Get()->Flush();
-
- /* == Step 4 == */
- grpc_pollset_add_fd(pollsets[2].pollset, tfds[3].fd);
- grpc_core::ExecCtx::Get()->Flush();
-
- /* All polling islands are merged at this point */
-
- /* Compare Fd:0's polling island with that of all other Fds */
- expected_pi = grpc_fd_get_polling_island(tfds[0].fd);
- for (i = 1; i < NUM_FDS; i++) {
- GPR_ASSERT(grpc_are_polling_islands_equal(
- expected_pi, grpc_fd_get_polling_island(tfds[i].fd)));
- }
-
- /* Compare Fd:0's polling island with that of all other pollsets */
- for (i = 0; i < NUM_POLLSETS; i++) {
- GPR_ASSERT(grpc_are_polling_islands_equal(
- expected_pi, grpc_pollset_get_polling_island(pollsets[i].pollset)));
- }
-
- test_fd_cleanup(tfds, NUM_FDS);
- test_pollset_cleanup(pollsets, NUM_POLLSETS);
-}
-
-#undef NUM_FDS
-#undef NUM_POLLSETS
-
-typedef struct threading_shared {
- gpr_mu* mu;
- grpc_pollset* pollset;
- grpc_wakeup_fd* wakeup_fd;
- grpc_fd* wakeup_desc;
- grpc_closure on_wakeup;
- int wakeups;
-} threading_shared;
-
-static __thread int thread_wakeups = 0;
-
-static void test_threading_loop(void* arg) {
- threading_shared* shared = static_cast<threading_shared*>(arg);
- while (thread_wakeups < 1000000) {
- grpc_core::ExecCtx exec_ctx;
- grpc_pollset_worker* worker;
- gpr_mu_lock(shared->mu);
- GPR_ASSERT(GRPC_LOG_IF_ERROR(
- "pollset_work",
- grpc_pollset_work(shared->pollset, &worker, GRPC_MILLIS_INF_FUTURE)));
- gpr_mu_unlock(shared->mu);
- }
-}
-
-static void test_threading_wakeup(void* arg, grpc_error* error) {
- threading_shared* shared = static_cast<threading_shared*>(arg);
- ++shared->wakeups;
- ++thread_wakeups;
- if (error == GRPC_ERROR_NONE) {
- GPR_ASSERT(GRPC_LOG_IF_ERROR(
- "consume_wakeup", grpc_wakeup_fd_consume_wakeup(shared->wakeup_fd)));
- grpc_fd_notify_on_read(shared->wakeup_desc, &shared->on_wakeup);
- GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_next",
- grpc_wakeup_fd_wakeup(shared->wakeup_fd)));
- }
-}
-
-static void test_threading(void) {
- threading_shared shared;
- shared.pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
- grpc_pollset_init(shared.pollset, &shared.mu);
-
- grpc_core::Thread thds[10];
- for (auto& th : thds) {
- th = grpc_core::Thread("test_thread", test_threading_loop, &shared);
- th.Start();
- }
- grpc_wakeup_fd fd;
- GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd)));
- shared.wakeup_fd = &fd;
- shared.wakeup_desc = grpc_fd_create(fd.read_fd, "wakeup", false);
- shared.wakeups = 0;
- {
- grpc_core::ExecCtx exec_ctx;
- grpc_pollset_add_fd(shared.pollset, shared.wakeup_desc);
- grpc_fd_notify_on_read(
- shared.wakeup_desc,
- GRPC_CLOSURE_INIT(&shared.on_wakeup, test_threading_wakeup, &shared,
- grpc_schedule_on_exec_ctx));
- }
- GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_first",
- grpc_wakeup_fd_wakeup(shared.wakeup_fd)));
- for (auto& th : thds) {
- th.Join();
- }
- fd.read_fd = 0;
- grpc_wakeup_fd_destroy(&fd);
- {
- grpc_core::ExecCtx exec_ctx;
- grpc_fd_shutdown(shared.wakeup_desc, GRPC_ERROR_CANCELLED);
- grpc_fd_orphan(shared.wakeup_desc, nullptr, nullptr, "done");
- grpc_pollset_shutdown(shared.pollset,
- GRPC_CLOSURE_CREATE(destroy_pollset, shared.pollset,
- grpc_schedule_on_exec_ctx));
- }
- gpr_free(shared.pollset);
-}
-
-int main(int argc, char** argv) {
- const char* poll_strategy = nullptr;
- grpc_test_init(argc, argv);
- grpc_init();
- {
- grpc_core::ExecCtx exec_ctx;
-
- poll_strategy = grpc_get_poll_strategy_name();
- if (poll_strategy != nullptr && strcmp(poll_strategy, "epollsig") == 0) {
- test_add_fd_to_pollset();
- test_threading();
- } else {
- gpr_log(GPR_INFO,
- "Skipping the test. The test is only relevant for 'epollsig' "
- "strategy. and the current strategy is: '%s'",
- poll_strategy);
- }
- }
-
- grpc_shutdown();
- return 0;
-}
-#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
-int main(int argc, char** argv) { return 0; }
-#endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */
diff --git a/test/core/iomgr/pollset_set_test.cc b/test/core/iomgr/pollset_set_test.cc
deleted file mode 100644
index 1aae1daa02..0000000000
--- a/test/core/iomgr/pollset_set_test.cc
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- *
- * 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.
- *
- */
-#include "src/core/lib/iomgr/port.h"
-
-/* This test only relevant on linux systems where epoll is available */
-#ifdef GRPC_LINUX_EPOLL_CREATE1
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/iomgr/ev_posix.h"
-#include "src/core/lib/iomgr/iomgr.h"
-#include "test/core/util/test_config.h"
-
-/*******************************************************************************
- * test_pollset_set
- */
-
-typedef struct test_pollset_set {
- grpc_pollset_set* pss;
-} test_pollset_set;
-
-void init_test_pollset_sets(test_pollset_set* pollset_sets, const int num_pss) {
- for (int i = 0; i < num_pss; i++) {
- pollset_sets[i].pss = grpc_pollset_set_create();
- }
-}
-
-void cleanup_test_pollset_sets(test_pollset_set* pollset_sets,
- const int num_pss) {
- for (int i = 0; i < num_pss; i++) {
- grpc_pollset_set_destroy(pollset_sets[i].pss);
- pollset_sets[i].pss = nullptr;
- }
-}
-
-/*******************************************************************************
- * test_pollset
- */
-
-typedef struct test_pollset {
- grpc_pollset* ps;
- gpr_mu* mu;
-} test_pollset;
-
-static void init_test_pollsets(test_pollset* pollsets, const int num_pollsets) {
- for (int i = 0; i < num_pollsets; i++) {
- pollsets[i].ps =
- static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
- grpc_pollset_init(pollsets[i].ps, &pollsets[i].mu);
- }
-}
-
-static void destroy_pollset(void* p, grpc_error* error) {
- grpc_pollset_destroy(static_cast<grpc_pollset*>(p));
-}
-
-static void cleanup_test_pollsets(test_pollset* pollsets,
- const int num_pollsets) {
- grpc_closure destroyed;
- for (int i = 0; i < num_pollsets; i++) {
- GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, pollsets[i].ps,
- grpc_schedule_on_exec_ctx);
- grpc_pollset_shutdown(pollsets[i].ps, &destroyed);
-
- grpc_core::ExecCtx::Get()->Flush();
- gpr_free(pollsets[i].ps);
- pollsets[i].ps = nullptr;
- }
-}
-
-/*******************************************************************************
- * test_fd
- */
-
-typedef struct test_fd {
- grpc_fd* fd;
- grpc_wakeup_fd wakeup_fd;
-
- bool is_on_readable_called; /* Is on_readable closure is called ? */
- grpc_closure on_readable; /* Closure to call when this fd is readable */
-} test_fd;
-
-void on_readable(void* tfd, grpc_error* error) {
- (static_cast<test_fd*>(tfd))->is_on_readable_called = true;
-}
-
-static void reset_test_fd(test_fd* tfd) {
- tfd->is_on_readable_called = false;
-
- GRPC_CLOSURE_INIT(&tfd->on_readable, on_readable, tfd,
- grpc_schedule_on_exec_ctx);
- grpc_fd_notify_on_read(tfd->fd, &tfd->on_readable);
-}
-
-static void init_test_fds(test_fd* tfds, const int num_fds) {
- for (int i = 0; i < num_fds; i++) {
- GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_init(&tfds[i].wakeup_fd));
- tfds[i].fd = grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&tfds[i].wakeup_fd),
- "test_fd", false);
- reset_test_fd(&tfds[i]);
- }
-}
-
-static void cleanup_test_fds(test_fd* tfds, const int num_fds) {
- int release_fd;
-
- for (int i = 0; i < num_fds; i++) {
- grpc_fd_shutdown(tfds[i].fd,
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd cleanup"));
- grpc_core::ExecCtx::Get()->Flush();
-
- /* grpc_fd_orphan frees the memory allocated for grpc_fd. Normally it also
- * calls close() on the underlying fd. In our case, we are using
- * grpc_wakeup_fd and we would like to destroy it ourselves (by calling
- * grpc_wakeup_fd_destroy). To prevent grpc_fd from calling close() on the
- * underlying fd, call it with a non-NULL 'release_fd' parameter */
- grpc_fd_orphan(tfds[i].fd, nullptr, &release_fd, "test_fd_cleanup");
- grpc_core::ExecCtx::Get()->Flush();
-
- grpc_wakeup_fd_destroy(&tfds[i].wakeup_fd);
- }
-}
-
-static void make_test_fds_readable(test_fd* tfds, const int num_fds) {
- for (int i = 0; i < num_fds; i++) {
- GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_wakeup(&tfds[i].wakeup_fd));
- }
-}
-
-static void verify_readable_and_reset(test_fd* tfds, const int num_fds) {
- for (int i = 0; i < num_fds; i++) {
- /* Verify that the on_readable callback was called */
- GPR_ASSERT(tfds[i].is_on_readable_called);
-
- /* Reset the tfd[i] structure */
- GPR_ASSERT(GRPC_ERROR_NONE ==
- grpc_wakeup_fd_consume_wakeup(&tfds[i].wakeup_fd));
- reset_test_fd(&tfds[i]);
- }
-}
-
-/*******************************************************************************
- * Main tests
- */
-
-/* Test some typical scenarios in pollset_set */
-static void pollset_set_test_basic() {
- /* We construct the following structure for this test:
- *
- * +---> FD0 (Added before PSS1, PS1 and PS2 are added to PSS0)
- * |
- * +---> FD5 (Added after PSS1, PS1 and PS2 are added to PSS0)
- * |
- * |
- * | +---> FD1 (Added before PSS1 is added to PSS0)
- * | |
- * | +---> FD6 (Added after PSS1 is added to PSS0)
- * | |
- * +---> PSS1--+ +--> FD2 (Added before PS0 is added to PSS1)
- * | | |
- * | +---> PS0---+
- * | |
- * PSS0---+ +--> FD7 (Added after PS0 is added to PSS1)
- * |
- * |
- * | +---> FD3 (Added before PS1 is added to PSS0)
- * | |
- * +---> PS1---+
- * | |
- * | +---> FD8 (Added after PS1 added to PSS0)
- * |
- * |
- * | +---> FD4 (Added before PS2 is added to PSS0)
- * | |
- * +---> PS2---+
- * |
- * +---> FD9 (Added after PS2 is added to PSS0)
- */
- grpc_core::ExecCtx exec_ctx;
- grpc_pollset_worker* worker;
- grpc_millis deadline;
-
- test_fd tfds[10];
- test_pollset pollsets[3];
- test_pollset_set pollset_sets[2];
- const int num_fds = GPR_ARRAY_SIZE(tfds);
- const int num_ps = GPR_ARRAY_SIZE(pollsets);
- const int num_pss = GPR_ARRAY_SIZE(pollset_sets);
-
- init_test_fds(tfds, num_fds);
- init_test_pollsets(pollsets, num_ps);
- init_test_pollset_sets(pollset_sets, num_pss);
-
- /* Construct the pollset_set/pollset/fd tree (see diagram above) */
-
- grpc_pollset_set_add_fd(pollset_sets[0].pss, tfds[0].fd);
- grpc_pollset_set_add_fd(pollset_sets[1].pss, tfds[1].fd);
-
- grpc_pollset_add_fd(pollsets[0].ps, tfds[2].fd);
- grpc_pollset_add_fd(pollsets[1].ps, tfds[3].fd);
- grpc_pollset_add_fd(pollsets[2].ps, tfds[4].fd);
-
- grpc_pollset_set_add_pollset_set(pollset_sets[0].pss, pollset_sets[1].pss);
-
- grpc_pollset_set_add_pollset(pollset_sets[1].pss, pollsets[0].ps);
- grpc_pollset_set_add_pollset(pollset_sets[0].pss, pollsets[1].ps);
- grpc_pollset_set_add_pollset(pollset_sets[0].pss, pollsets[2].ps);
-
- grpc_pollset_set_add_fd(pollset_sets[0].pss, tfds[5].fd);
- grpc_pollset_set_add_fd(pollset_sets[1].pss, tfds[6].fd);
-
- grpc_pollset_add_fd(pollsets[0].ps, tfds[7].fd);
- grpc_pollset_add_fd(pollsets[1].ps, tfds[8].fd);
- grpc_pollset_add_fd(pollsets[2].ps, tfds[9].fd);
-
- grpc_core::ExecCtx::Get()->Flush();
-
- /* Test that if any FD in the above structure is readable, it is observable by
- * doing grpc_pollset_work on any pollset
- *
- * For every pollset, do the following:
- * - (Ensure that all FDs are in reset state)
- * - Make all FDs readable
- * - Call grpc_pollset_work() on the pollset
- * - Flush the exec_ctx
- * - Verify that on_readable call back was called for all FDs (and
- * reset the FDs)
- * */
- for (int i = 0; i < num_ps; i++) {
- make_test_fds_readable(tfds, num_fds);
-
- gpr_mu_lock(pollsets[i].mu);
- deadline = grpc_timespec_to_millis_round_up(
- grpc_timeout_milliseconds_to_deadline(2));
- GPR_ASSERT(GRPC_ERROR_NONE ==
- grpc_pollset_work(pollsets[i].ps, &worker, deadline));
- gpr_mu_unlock(pollsets[i].mu);
-
- grpc_core::ExecCtx::Get()->Flush();
-
- verify_readable_and_reset(tfds, num_fds);
- grpc_core::ExecCtx::Get()->Flush();
- }
-
- /* Test tear down */
- grpc_pollset_set_del_fd(pollset_sets[0].pss, tfds[0].fd);
- grpc_pollset_set_del_fd(pollset_sets[0].pss, tfds[5].fd);
- grpc_pollset_set_del_fd(pollset_sets[1].pss, tfds[1].fd);
- grpc_pollset_set_del_fd(pollset_sets[1].pss, tfds[6].fd);
- grpc_core::ExecCtx::Get()->Flush();
-
- grpc_pollset_set_del_pollset(pollset_sets[1].pss, pollsets[0].ps);
- grpc_pollset_set_del_pollset(pollset_sets[0].pss, pollsets[1].ps);
- grpc_pollset_set_del_pollset(pollset_sets[0].pss, pollsets[2].ps);
-
- grpc_pollset_set_del_pollset_set(pollset_sets[0].pss, pollset_sets[1].pss);
- grpc_core::ExecCtx::Get()->Flush();
-
- cleanup_test_fds(tfds, num_fds);
- cleanup_test_pollsets(pollsets, num_ps);
- cleanup_test_pollset_sets(pollset_sets, num_pss);
-}
-
-/* Same FD added multiple times to the pollset_set tree */
-void pollset_set_test_dup_fds() {
- /* We construct the following structure for this test:
- *
- * +---> FD0
- * |
- * |
- * PSS0---+
- * | +---> FD0 (also under PSS0)
- * | |
- * +---> PSS1--+ +--> FD1 (also under PSS1)
- * | |
- * +---> PS ---+
- * | |
- * | +--> FD2
- * +---> FD1
- */
- grpc_core::ExecCtx exec_ctx;
- grpc_pollset_worker* worker;
- grpc_millis deadline;
-
- test_fd tfds[3];
- test_pollset pollset;
- test_pollset_set pollset_sets[2];
- const int num_fds = GPR_ARRAY_SIZE(tfds);
- const int num_ps = 1;
- const int num_pss = GPR_ARRAY_SIZE(pollset_sets);
-
- init_test_fds(tfds, num_fds);
- init_test_pollsets(&pollset, num_ps);
- init_test_pollset_sets(pollset_sets, num_pss);
-
- /* Construct the structure */
- grpc_pollset_set_add_fd(pollset_sets[0].pss, tfds[0].fd);
- grpc_pollset_set_add_fd(pollset_sets[1].pss, tfds[0].fd);
- grpc_pollset_set_add_fd(pollset_sets[1].pss, tfds[1].fd);
-
- grpc_pollset_add_fd(pollset.ps, tfds[1].fd);
- grpc_pollset_add_fd(pollset.ps, tfds[2].fd);
-
- grpc_pollset_set_add_pollset(pollset_sets[1].pss, pollset.ps);
- grpc_pollset_set_add_pollset_set(pollset_sets[0].pss, pollset_sets[1].pss);
-
- /* Test. Make all FDs readable and make sure that can be observed by doing a
- * grpc_pollset_work on the pollset 'PS' */
- make_test_fds_readable(tfds, num_fds);
-
- gpr_mu_lock(pollset.mu);
- deadline = grpc_timespec_to_millis_round_up(
- grpc_timeout_milliseconds_to_deadline(2));
- GPR_ASSERT(GRPC_ERROR_NONE ==
- grpc_pollset_work(pollset.ps, &worker, deadline));
- gpr_mu_unlock(pollset.mu);
- grpc_core::ExecCtx::Get()->Flush();
-
- verify_readable_and_reset(tfds, num_fds);
- grpc_core::ExecCtx::Get()->Flush();
-
- /* Tear down */
- grpc_pollset_set_del_fd(pollset_sets[0].pss, tfds[0].fd);
- grpc_pollset_set_del_fd(pollset_sets[1].pss, tfds[0].fd);
- grpc_pollset_set_del_fd(pollset_sets[1].pss, tfds[1].fd);
-
- grpc_pollset_set_del_pollset(pollset_sets[1].pss, pollset.ps);
- grpc_pollset_set_del_pollset_set(pollset_sets[0].pss, pollset_sets[1].pss);
- grpc_core::ExecCtx::Get()->Flush();
-
- cleanup_test_fds(tfds, num_fds);
- cleanup_test_pollsets(&pollset, num_ps);
- cleanup_test_pollset_sets(pollset_sets, num_pss);
-}
-
-/* Pollset_set with an empty pollset */
-void pollset_set_test_empty_pollset() {
- /* We construct the following structure for this test:
- *
- * +---> PS0 (EMPTY)
- * |
- * +---> FD0
- * |
- * PSS0---+
- * | +---> FD1
- * | |
- * +---> PS1--+
- * |
- * +---> FD2
- */
- grpc_core::ExecCtx exec_ctx;
- grpc_pollset_worker* worker;
- grpc_millis deadline;
-
- test_fd tfds[3];
- test_pollset pollsets[2];
- test_pollset_set pollset_set;
- const int num_fds = GPR_ARRAY_SIZE(tfds);
- const int num_ps = GPR_ARRAY_SIZE(pollsets);
- const int num_pss = 1;
-
- init_test_fds(tfds, num_fds);
- init_test_pollsets(pollsets, num_ps);
- init_test_pollset_sets(&pollset_set, num_pss);
-
- /* Construct the structure */
- grpc_pollset_set_add_fd(pollset_set.pss, tfds[0].fd);
- grpc_pollset_add_fd(pollsets[1].ps, tfds[1].fd);
- grpc_pollset_add_fd(pollsets[1].ps, tfds[2].fd);
-
- grpc_pollset_set_add_pollset(pollset_set.pss, pollsets[0].ps);
- grpc_pollset_set_add_pollset(pollset_set.pss, pollsets[1].ps);
-
- /* Test. Make all FDs readable and make sure that can be observed by doing
- * grpc_pollset_work on the empty pollset 'PS0' */
- make_test_fds_readable(tfds, num_fds);
-
- gpr_mu_lock(pollsets[0].mu);
- deadline = grpc_timespec_to_millis_round_up(
- grpc_timeout_milliseconds_to_deadline(2));
- GPR_ASSERT(GRPC_ERROR_NONE ==
- grpc_pollset_work(pollsets[0].ps, &worker, deadline));
- gpr_mu_unlock(pollsets[0].mu);
- grpc_core::ExecCtx::Get()->Flush();
-
- verify_readable_and_reset(tfds, num_fds);
- grpc_core::ExecCtx::Get()->Flush();
-
- /* Tear down */
- grpc_pollset_set_del_fd(pollset_set.pss, tfds[0].fd);
- grpc_pollset_set_del_pollset(pollset_set.pss, pollsets[0].ps);
- grpc_pollset_set_del_pollset(pollset_set.pss, pollsets[1].ps);
- grpc_core::ExecCtx::Get()->Flush();
-
- cleanup_test_fds(tfds, num_fds);
- cleanup_test_pollsets(pollsets, num_ps);
- cleanup_test_pollset_sets(&pollset_set, num_pss);
-}
-
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- grpc_init();
- {
- grpc_core::ExecCtx exec_ctx;
- const char* poll_strategy = grpc_get_poll_strategy_name();
-
- if (poll_strategy != nullptr &&
- (strcmp(poll_strategy, "epollsig") == 0 ||
- strcmp(poll_strategy, "epoll-threadpool") == 0)) {
- pollset_set_test_basic();
- pollset_set_test_dup_fds();
- pollset_set_test_empty_pollset();
- } else {
- gpr_log(GPR_INFO,
- "Skipping the test. The test is only relevant for 'epoll' "
- "strategy. and the current strategy is: '%s'",
- poll_strategy);
- }
- }
- grpc_shutdown();
- return 0;
-}
-#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
-int main(int argc, char** argv) { return 0; }
-#endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */
diff --git a/test/core/surface/completion_queue_test.cc b/test/core/surface/completion_queue_test.cc
index b889fd0fc6..f7ce8a7042 100644
--- a/test/core/surface/completion_queue_test.cc
+++ b/test/core/surface/completion_queue_test.cc
@@ -369,11 +369,15 @@ static void test_callback(void) {
LOG_TEST("test_callback");
bool got_shutdown = false;
- class ShutdownCallback : public grpc_core::CQCallbackInterface {
+ class ShutdownCallback : public grpc_experimental_completion_queue_functor {
public:
- ShutdownCallback(bool* done) : done_(done) {}
+ ShutdownCallback(bool* done) : done_(done) {
+ functor_run = &ShutdownCallback::Run;
+ }
~ShutdownCallback() {}
- void Run(bool ok) override { *done_ = ok; }
+ static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
+ *static_cast<ShutdownCallback*>(cb)->done_ = static_cast<bool>(ok);
+ }
private:
bool* done_;
@@ -391,14 +395,17 @@ static void test_callback(void) {
grpc_completion_queue_factory_lookup(&attr), &attr, nullptr);
int counter = 0;
- class TagCallback : public grpc_core::CQCallbackInterface {
+ class TagCallback : public grpc_experimental_completion_queue_functor {
public:
- TagCallback(int* counter, int tag) : counter_(counter), tag_(tag) {}
+ TagCallback(int* counter, int tag) : counter_(counter), tag_(tag) {
+ functor_run = &TagCallback::Run;
+ }
~TagCallback() {}
- void Run(bool ok) override {
- GPR_ASSERT(ok);
- *counter_ += tag_;
- grpc_core::Delete(this);
+ static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
+ GPR_ASSERT(static_cast<bool>(ok));
+ auto* callback = static_cast<TagCallback*>(cb);
+ *callback->counter_ += callback->tag_;
+ grpc_core::Delete(callback);
};
private:
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index b0af788796..3ebdb88a08 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -139,6 +139,7 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_channelz_get_servers);
printf("%lx", (unsigned long) grpc_channelz_get_channel);
printf("%lx", (unsigned long) grpc_channelz_get_subchannel);
+ printf("%lx", (unsigned long) grpc_channelz_get_socket);
printf("%lx", (unsigned long) grpc_auth_property_iterator_next);
printf("%lx", (unsigned long) grpc_auth_context_property_iterator);
printf("%lx", (unsigned long) grpc_auth_context_peer_identity);
diff --git a/test/core/tsi/alts/fake_handshaker/BUILD b/test/core/tsi/alts/fake_handshaker/BUILD
index a09a046d27..98cd628a7d 100644
--- a/test/core/tsi/alts/fake_handshaker/BUILD
+++ b/test/core/tsi/alts/fake_handshaker/BUILD
@@ -37,21 +37,22 @@ grpc_cc_library(
name = "fake_handshaker_lib",
testonly = True,
srcs = ["fake_handshaker_server.cc"],
+ hdrs = ["fake_handshaker_server.h"],
language = "C++",
deps = [
"handshaker_proto",
"transport_security_common_proto",
"//:grpc++",
- "//test/cpp/util:test_config",
],
)
grpc_cc_binary(
name = "fake_handshaker_server",
testonly = True,
- srcs = ["fake_handshaker_server.cc"],
+ srcs = ["fake_handshaker_server_main.cc"],
language = "C++",
deps = [
+ "//test/cpp/util:test_config",
"fake_handshaker_lib",
],
)
diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
index f6a4791b49..ba246b07eb 100644
--- a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
+++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
@@ -15,12 +15,12 @@
* limitations under the License.
*
*/
+#include "test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h"
#include <memory>
#include <sstream>
#include <string>
-#include <gflags/gflags.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpcpp/impl/codegen/async_stream.h>
@@ -32,10 +32,6 @@
#include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
#include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
#include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
-#include "test/cpp/util/test_config.h"
-
-DEFINE_int32(handshaker_port, 55056,
- "TCP port on which the fake handshaker server listens to.");
// Fake handshake messages.
constexpr char kClientInitFrame[] = "ClientInit";
@@ -243,26 +239,9 @@ class FakeHandshakerService : public HandshakerService::Service {
}
};
-} // namespace gcp
-} // namespace grpc
-
-void RunServer() {
- GPR_ASSERT(FLAGS_handshaker_port != 0);
- std::ostringstream server_address;
- server_address << "[::1]:" << FLAGS_handshaker_port;
- grpc::gcp::FakeHandshakerService service;
- grpc::ServerBuilder builder;
- builder.AddListeningPort(server_address.str(),
- grpc::InsecureServerCredentials());
- builder.RegisterService(&service);
- std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
- gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
- server_address.str().c_str());
- server->Wait();
+std::unique_ptr<grpc::Service> CreateFakeHandshakerService() {
+ return std::unique_ptr<grpc::Service>{new grpc::gcp::FakeHandshakerService};
}
-int main(int argc, char** argv) {
- grpc::testing::InitTest(&argc, &argv, true);
- RunServer();
- return 0;
-}
+} // namespace gcp
+} // namespace grpc
diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h
new file mode 100644
index 0000000000..eb4bfdffa1
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2018 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 <memory>
+#include <string>
+
+#include <grpcpp/grpcpp.h>
+
+namespace grpc {
+namespace gcp {
+
+std::unique_ptr<grpc::Service> CreateFakeHandshakerService();
+
+} // namespace gcp
+} // namespace grpc
diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server_main.cc b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server_main.cc
new file mode 100644
index 0000000000..60351533d9
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server_main.cc
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2018 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 "test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h"
+
+#include <sstream>
+
+#include <gflags/gflags.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/server_builder.h>
+
+#include "test/cpp/util/test_config.h"
+
+DEFINE_int32(handshaker_port, 55056,
+ "TCP port on which the fake handshaker server listens to.");
+
+static void RunFakeHandshakerServer(const std::string& server_address) {
+ std::unique_ptr<grpc::Service> service =
+ grpc::gcp::CreateFakeHandshakerService();
+ grpc::ServerBuilder builder;
+ builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
+ builder.RegisterService(service.get());
+ gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
+ server_address.c_str());
+ std::unique_ptr<grpc::Server> server = builder.BuildAndStart();
+ server->Wait();
+}
+
+int main(int argc, char** argv) {
+ grpc::testing::InitTest(&argc, &argv, true);
+
+ GPR_ASSERT(FLAGS_handshaker_port != 0);
+ std::ostringstream server_address;
+ server_address << "[::1]:" << FLAGS_handshaker_port;
+
+ RunFakeHandshakerServer(server_address.str());
+ return 0;
+}
diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden
index 756f6a0224..93e1e68654 100644
--- a/test/cpp/codegen/compiler_test_golden
+++ b/test/cpp/codegen/compiler_test_golden
@@ -26,6 +26,7 @@
#include "src/proto/grpc/testing/compiler_test.pb.h"
+#include <functional>
#include <grpcpp/impl/codegen/async_generic_service.h>
#include <grpcpp/impl/codegen/async_stream.h>
#include <grpcpp/impl/codegen/async_unary_call.h>
@@ -105,6 +106,23 @@ class ServiceA final {
return std::unique_ptr< ::grpc::ClientAsyncReaderWriterInterface< ::grpc::testing::Request, ::grpc::testing::Response>>(PrepareAsyncMethodA4Raw(context, cq));
}
// Method A4 trailing comment 1
+ class experimental_async_interface {
+ public:
+ virtual ~experimental_async_interface() {}
+ // MethodA1 leading comment 1
+ virtual void MethodA1(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, std::function<void(::grpc::Status)>) = 0;
+ // MethodA1 trailing comment 1
+ // MethodA2 detached leading comment 1
+ //
+ // Method A2 leading comment 1
+ // Method A2 leading comment 2
+ // MethodA2 trailing comment 1
+ // Method A3 leading comment 1
+ // Method A3 trailing comment 1
+ // Method A4 leading comment 1
+ // Method A4 trailing comment 1
+ };
+ virtual class experimental_async_interface* experimental_async() { return nullptr; }
private:
virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc::testing::Response>* AsyncMethodA1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) = 0;
virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc::testing::Response>* PrepareAsyncMethodA1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) = 0;
@@ -155,9 +173,21 @@ class ServiceA final {
std::unique_ptr< ::grpc::ClientAsyncReaderWriter< ::grpc::testing::Request, ::grpc::testing::Response>> PrepareAsyncMethodA4(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncReaderWriter< ::grpc::testing::Request, ::grpc::testing::Response>>(PrepareAsyncMethodA4Raw(context, cq));
}
+ class experimental_async final :
+ public StubInterface::experimental_async_interface {
+ public:
+ void MethodA1(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, std::function<void(::grpc::Status)>) override;
+ private:
+ friend class Stub;
+ explicit experimental_async(Stub* stub): stub_(stub) { }
+ Stub* stub() { return stub_; }
+ Stub* stub_;
+ };
+ class experimental_async_interface* experimental_async() override { return &async_stub_; }
private:
std::shared_ptr< ::grpc::ChannelInterface> channel_;
+ class experimental_async async_stub_{this};
::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>* AsyncMethodA1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) override;
::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>* PrepareAsyncMethodA1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) override;
::grpc::ClientWriter< ::grpc::testing::Request>* MethodA2Raw(::grpc::ClientContext* context, ::grpc::testing::Response* response) override;
@@ -488,6 +518,14 @@ class ServiceB final {
return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc::testing::Response>>(PrepareAsyncMethodB1Raw(context, request, cq));
}
// MethodB1 trailing comment 1
+ class experimental_async_interface {
+ public:
+ virtual ~experimental_async_interface() {}
+ // MethodB1 leading comment 1
+ virtual void MethodB1(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, std::function<void(::grpc::Status)>) = 0;
+ // MethodB1 trailing comment 1
+ };
+ virtual class experimental_async_interface* experimental_async() { return nullptr; }
private:
virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc::testing::Response>* AsyncMethodB1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) = 0;
virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc::testing::Response>* PrepareAsyncMethodB1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) = 0;
@@ -502,9 +540,21 @@ class ServiceB final {
std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>> PrepareAsyncMethodB1(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>>(PrepareAsyncMethodB1Raw(context, request, cq));
}
+ class experimental_async final :
+ public StubInterface::experimental_async_interface {
+ public:
+ void MethodB1(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, std::function<void(::grpc::Status)>) override;
+ private:
+ friend class Stub;
+ explicit experimental_async(Stub* stub): stub_(stub) { }
+ Stub* stub() { return stub_; }
+ Stub* stub_;
+ };
+ class experimental_async_interface* experimental_async() override { return &async_stub_; }
private:
std::shared_ptr< ::grpc::ChannelInterface> channel_;
+ class experimental_async async_stub_{this};
::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>* AsyncMethodB1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) override;
::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>* PrepareAsyncMethodB1Raw(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) override;
const ::grpc::internal::RpcMethod rpcmethod_MethodB1_;
diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc
index e96d68f93b..a597fd9c4b 100644
--- a/test/cpp/end2end/channelz_service_test.cc
+++ b/test/cpp/end2end/channelz_service_test.cc
@@ -43,6 +43,8 @@ using grpc::channelz::v1::GetChannelRequest;
using grpc::channelz::v1::GetChannelResponse;
using grpc::channelz::v1::GetServersRequest;
using grpc::channelz::v1::GetServersResponse;
+using grpc::channelz::v1::GetSocketRequest;
+using grpc::channelz::v1::GetSocketResponse;
using grpc::channelz::v1::GetSubchannelRequest;
using grpc::channelz::v1::GetSubchannelResponse;
using grpc::channelz::v1::GetTopChannelsRequest;
@@ -71,6 +73,26 @@ class Proxy : public ::grpc::testing::EchoTestService::Service {
return stubs_[idx]->Echo(client_context.get(), *request, response);
}
+ Status BidiStream(ServerContext* server_context,
+ ServerReaderWriter<EchoResponse, EchoRequest>*
+ stream_from_client) override {
+ EchoRequest request;
+ EchoResponse response;
+ std::unique_ptr<ClientContext> client_context =
+ ClientContext::FromServerContext(*server_context);
+
+ // always use the first proxy for streaming
+ auto stream_to_backend = stubs_[0]->BidiStream(client_context.get());
+ while (stream_from_client->Read(&request)) {
+ stream_to_backend->Write(request);
+ stream_to_backend->Read(&response);
+ stream_from_client->Write(response);
+ }
+
+ stream_to_backend->WritesDone();
+ return stream_to_backend->Finish();
+ }
+
private:
std::vector<std::unique_ptr<::grpc::testing::EchoTestService::Stub>> stubs_;
};
@@ -149,6 +171,21 @@ class ChannelzServerTest : public ::testing::Test {
EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
}
+ void SendSuccessfulStream(int num_messages) {
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello channelz");
+ ClientContext context;
+ auto stream_to_proxy = echo_stub_->BidiStream(&context);
+ for (int i = 0; i < num_messages; ++i) {
+ EXPECT_TRUE(stream_to_proxy->Write(request));
+ EXPECT_TRUE(stream_to_proxy->Read(&response));
+ }
+ stream_to_proxy->WritesDone();
+ Status s = stream_to_proxy->Finish();
+ EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
+ }
+
void SendFailedEcho(int channel_idx) {
EchoRequest request;
EchoResponse response;
@@ -448,6 +485,121 @@ TEST_F(ChannelzServerTest, ServerCallTest) {
kNumSuccess + kNumFailed + 1);
}
+TEST_F(ChannelzServerTest, ManySubchannelsAndSockets) {
+ ResetStubs();
+ const int kNumChannels = 4;
+ ConfigureProxy(kNumChannels);
+ const int kNumSuccess = 10;
+ const int kNumFailed = 11;
+ for (int i = 0; i < kNumSuccess; ++i) {
+ SendSuccessfulEcho(0);
+ SendSuccessfulEcho(2);
+ }
+ for (int i = 0; i < kNumFailed; ++i) {
+ SendFailedEcho(1);
+ SendFailedEcho(2);
+ }
+ GetTopChannelsRequest gtc_request;
+ GetTopChannelsResponse gtc_response;
+ gtc_request.set_start_channel_id(0);
+ ClientContext context;
+ Status s =
+ channelz_stub_->GetTopChannels(&context, gtc_request, &gtc_response);
+ EXPECT_TRUE(s.ok()) << s.error_message();
+ EXPECT_EQ(gtc_response.channel_size(), kNumChannels);
+ for (int i = 0; i < gtc_response.channel_size(); ++i) {
+ // if the channel sent no RPCs, then expect no subchannels to have been
+ // created.
+ if (gtc_response.channel(i).data().calls_started() == 0) {
+ EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0);
+ continue;
+ }
+ // The resolver must return at least one address.
+ ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0);
+ // First grab the subchannel
+ GetSubchannelRequest get_subchannel_req;
+ GetSubchannelResponse get_subchannel_resp;
+ get_subchannel_req.set_subchannel_id(
+ gtc_response.channel(i).subchannel_ref(0).subchannel_id());
+ ClientContext get_subchannel_ctx;
+ Status s = channelz_stub_->GetSubchannel(
+ &get_subchannel_ctx, get_subchannel_req, &get_subchannel_resp);
+ EXPECT_TRUE(s.ok()) << s.error_message();
+ EXPECT_EQ(get_subchannel_resp.subchannel().socket_ref_size(), 1);
+ // Now grab the socket.
+ GetSocketRequest get_socket_req;
+ GetSocketResponse get_socket_resp;
+ ClientContext get_socket_ctx;
+ get_socket_req.set_socket_id(
+ get_subchannel_resp.subchannel().socket_ref(0).socket_id());
+ s = channelz_stub_->GetSocket(&get_socket_ctx, get_socket_req,
+ &get_socket_resp);
+ EXPECT_TRUE(s.ok()) << s.error_message();
+ // calls started == streams started AND stream succeeded. Since none of
+ // these RPCs were canceled, all of the streams will succeeded even though
+ // the RPCs they represent might have failed.
+ EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
+ get_socket_resp.socket().data().streams_started());
+ EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
+ get_socket_resp.socket().data().streams_succeeded());
+ // All of the calls were unary, so calls started == messages sent.
+ EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
+ get_socket_resp.socket().data().messages_sent());
+ // We only get responses when the RPC was successful, so
+ // calls succeeded == messages received.
+ EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_succeeded(),
+ get_socket_resp.socket().data().messages_received());
+ }
+}
+
+TEST_F(ChannelzServerTest, StreamingRPC) {
+ ResetStubs();
+ ConfigureProxy(1);
+ const int kNumMessages = 5;
+ SendSuccessfulStream(kNumMessages);
+ // Get the channel
+ GetChannelRequest get_channel_request;
+ GetChannelResponse get_channel_response;
+ get_channel_request.set_channel_id(GetChannelId(0));
+ ClientContext get_channel_context;
+ Status s = channelz_stub_->GetChannel(
+ &get_channel_context, get_channel_request, &get_channel_response);
+ EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
+ EXPECT_EQ(get_channel_response.channel().data().calls_started(), 1);
+ EXPECT_EQ(get_channel_response.channel().data().calls_succeeded(), 1);
+ EXPECT_EQ(get_channel_response.channel().data().calls_failed(), 0);
+ // Get the subchannel
+ ASSERT_GT(get_channel_response.channel().subchannel_ref_size(), 0);
+ GetSubchannelRequest get_subchannel_request;
+ GetSubchannelResponse get_subchannel_response;
+ ClientContext get_subchannel_context;
+ get_subchannel_request.set_subchannel_id(
+ get_channel_response.channel().subchannel_ref(0).subchannel_id());
+ s = channelz_stub_->GetSubchannel(&get_subchannel_context,
+ get_subchannel_request,
+ &get_subchannel_response);
+ EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
+ EXPECT_EQ(get_subchannel_response.subchannel().data().calls_started(), 1);
+ EXPECT_EQ(get_subchannel_response.subchannel().data().calls_succeeded(), 1);
+ EXPECT_EQ(get_subchannel_response.subchannel().data().calls_failed(), 0);
+ // Get the socket
+ ASSERT_GT(get_subchannel_response.subchannel().socket_ref_size(), 0);
+ GetSocketRequest get_socket_request;
+ GetSocketResponse get_socket_response;
+ ClientContext get_socket_context;
+ get_socket_request.set_socket_id(
+ get_subchannel_response.subchannel().socket_ref(0).socket_id());
+ s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request,
+ &get_socket_response);
+ EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
+ EXPECT_EQ(get_socket_response.socket().data().streams_started(), 1);
+ EXPECT_EQ(get_socket_response.socket().data().streams_succeeded(), 1);
+ EXPECT_EQ(get_socket_response.socket().data().streams_failed(), 0);
+ EXPECT_EQ(get_socket_response.socket().data().messages_sent(), kNumMessages);
+ EXPECT_EQ(get_socket_response.socket().data().messages_received(),
+ kNumMessages);
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc
index d8cb44b694..62a85641c7 100644
--- a/test/cpp/end2end/client_callback_end2end_test.cc
+++ b/test/cpp/end2end/client_callback_end2end_test.cc
@@ -18,6 +18,7 @@
#include <functional>
#include <mutex>
+#include <thread>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
@@ -55,7 +56,8 @@ class ClientCallbackEnd2endTest : public ::testing::Test {
void ResetStub() {
ChannelArguments args;
channel_ = server_->InProcessChannel(args);
- stub_.reset(new GenericStub(channel_));
+ stub_ = grpc::testing::EchoTestService::NewStub(channel_);
+ generic_stub_.reset(new GenericStub(channel_));
}
void TearDown() override {
@@ -64,7 +66,45 @@ class ClientCallbackEnd2endTest : public ::testing::Test {
}
}
- void SendRpcs(int num_rpcs, bool maybe_except) {
+ void SendRpcs(int num_rpcs, bool with_binary_metadata) {
+ grpc::string test_string("");
+ for (int i = 0; i < num_rpcs; i++) {
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext cli_ctx;
+
+ test_string += "Hello world. ";
+ request.set_message(test_string);
+
+ if (with_binary_metadata) {
+ char bytes[8] = {'\0', '\1', '\2', '\3',
+ '\4', '\5', '\6', static_cast<char>(i)};
+ cli_ctx.AddMetadata("custom-bin", grpc::string(bytes, 8));
+ }
+
+ cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP);
+
+ std::mutex mu;
+ std::condition_variable cv;
+ bool done = false;
+ stub_->experimental_async()->Echo(
+ &cli_ctx, &request, &response,
+ [&request, &response, &done, &mu, &cv](Status s) {
+ GPR_ASSERT(s.ok());
+
+ EXPECT_EQ(request.message(), response.message());
+ std::lock_guard<std::mutex> l(mu);
+ done = true;
+ cv.notify_one();
+ });
+ std::unique_lock<std::mutex> l(mu);
+ while (!done) {
+ cv.wait(l);
+ }
+ }
+ }
+
+ void SendRpcsGeneric(int num_rpcs, bool maybe_except) {
const grpc::string kMethodName("/grpc.testing.EchoTestService/Echo");
grpc::string test_string("");
for (int i = 0; i < num_rpcs; i++) {
@@ -80,7 +120,7 @@ class ClientCallbackEnd2endTest : public ::testing::Test {
std::mutex mu;
std::condition_variable cv;
bool done = false;
- stub_->experimental().UnaryCall(
+ generic_stub_->experimental().UnaryCall(
&cli_ctx, kMethodName, send_buf.get(), &recv_buf,
[&request, &recv_buf, &done, &mu, &cv, maybe_except](Status s) {
GPR_ASSERT(s.ok());
@@ -105,9 +145,11 @@ class ClientCallbackEnd2endTest : public ::testing::Test {
}
}
}
+
bool is_server_started_;
std::shared_ptr<Channel> channel_;
- std::unique_ptr<grpc::GenericStub> stub_;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+ std::unique_ptr<grpc::GenericStub> generic_stub_;
TestServiceImpl service_;
std::unique_ptr<Server> server_;
};
@@ -122,13 +164,72 @@ TEST_F(ClientCallbackEnd2endTest, SequentialRpcs) {
SendRpcs(10, false);
}
+TEST_F(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) {
+ ResetStub();
+ SendRpcs(10, true);
+}
+
+TEST_F(ClientCallbackEnd2endTest, SequentialGenericRpcs) {
+ ResetStub();
+ SendRpcsGeneric(10, false);
+}
+
#if GRPC_ALLOW_EXCEPTIONS
TEST_F(ClientCallbackEnd2endTest, ExceptingRpc) {
ResetStub();
- SendRpcs(10, true);
+ SendRpcsGeneric(10, true);
}
#endif
+TEST_F(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) {
+ ResetStub();
+ std::vector<std::thread> threads;
+ threads.reserve(10);
+ for (int i = 0; i < 10; ++i) {
+ threads.emplace_back([this] { SendRpcs(10, true); });
+ }
+ for (int i = 0; i < 10; ++i) {
+ threads[i].join();
+ }
+}
+
+TEST_F(ClientCallbackEnd2endTest, MultipleRpcs) {
+ ResetStub();
+ std::vector<std::thread> threads;
+ threads.reserve(10);
+ for (int i = 0; i < 10; ++i) {
+ threads.emplace_back([this] { SendRpcs(10, false); });
+ }
+ for (int i = 0; i < 10; ++i) {
+ threads[i].join();
+ }
+}
+
+TEST_F(ClientCallbackEnd2endTest, CancelRpcBeforeStart) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+ request.set_message("hello");
+ context.TryCancel();
+
+ std::mutex mu;
+ std::condition_variable cv;
+ bool done = false;
+ stub_->experimental_async()->Echo(
+ &context, &request, &response, [&response, &done, &mu, &cv](Status s) {
+ EXPECT_EQ("", response.message());
+ EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code());
+ std::lock_guard<std::mutex> l(mu);
+ done = true;
+ cv.notify_one();
+ });
+ std::unique_lock<std::mutex> l(mu);
+ while (!done) {
+ cv.wait(l);
+ }
+}
+
} // namespace
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
index 6fcf048bf3..ba4b57ad22 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
@@ -27,6 +27,7 @@
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/static_metadata.h"
@@ -456,8 +457,9 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
grpc_chttp2_hpack_parser p;
grpc_chttp2_hpack_parser_init(&p);
+ const int kArenaSize = 4096 * 4096;
+ p.on_header_user_data = gpr_arena_create(kArenaSize);
p.on_header = OnHeader;
- p.on_header_user_data = nullptr;
for (auto slice : init_slices) {
GPR_ASSERT(GRPC_ERROR_NONE == grpc_chttp2_hpack_parser_parse(&p, slice));
}
@@ -466,7 +468,14 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
GPR_ASSERT(GRPC_ERROR_NONE == grpc_chttp2_hpack_parser_parse(&p, slice));
}
grpc_core::ExecCtx::Get()->Flush();
+ // Recreate arena every 4k iterations to avoid oom
+ if (0 == (state.iterations() & 0xfff)) {
+ gpr_arena_destroy((gpr_arena*)p.on_header_user_data);
+ p.on_header_user_data = gpr_arena_create(kArenaSize);
+ }
}
+ // Clean up
+ gpr_arena_destroy((gpr_arena*)p.on_header_user_data);
for (auto slice : init_slices) grpc_slice_unref(slice);
for (auto slice : benchmark_slices) grpc_slice_unref(slice);
grpc_chttp2_hpack_parser_destroy(&p);
@@ -766,8 +775,58 @@ class RepresentativeServerTrailingMetadata {
static void free_timeout(void* p) { gpr_free(p); }
-// New implementation.
-static void OnHeaderNew(void* user_data, grpc_mdelem md) {
+// Benchmark the current on_initial_header implementation
+static void OnInitialHeader(void* user_data, grpc_mdelem md) {
+ // Setup for benchmark. This will bloat the absolute values of this benchmark
+ grpc_chttp2_incoming_metadata_buffer buffer;
+ grpc_chttp2_incoming_metadata_buffer_init(&buffer, (gpr_arena*)user_data);
+ bool seen_error = false;
+
+ // Below here is the code we actually care about benchmarking
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+ !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
+ seen_error = true;
+ }
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
+ grpc_millis* cached_timeout =
+ static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
+ grpc_millis timeout;
+ if (cached_timeout != nullptr) {
+ timeout = *cached_timeout;
+ } else {
+ if (GPR_UNLIKELY(
+ !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
+ char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+ gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
+ gpr_free(val);
+ timeout = GRPC_MILLIS_INF_FUTURE;
+ }
+ if (GRPC_MDELEM_IS_INTERNED(md)) {
+ /* not already parsed: parse it now, and store the
+ * result away */
+ cached_timeout =
+ static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
+ *cached_timeout = timeout;
+ grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+ }
+ }
+ benchmark::DoNotOptimize(timeout);
+ GRPC_MDELEM_UNREF(md);
+ } else {
+ const size_t new_size = buffer.size + GRPC_MDELEM_LENGTH(md);
+ if (!seen_error) {
+ buffer.size = new_size;
+ }
+ grpc_error* error = grpc_chttp2_incoming_metadata_buffer_add(&buffer, md);
+ if (error != GRPC_ERROR_NONE) {
+ GPR_ASSERT(0);
+ }
+ }
+ grpc_chttp2_incoming_metadata_buffer_destroy(&buffer);
+}
+
+// Benchmark timeout handling
+static void OnHeaderTimeout(void* user_data, grpc_mdelem md) {
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
grpc_millis* cached_timeout =
static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
@@ -853,8 +912,13 @@ BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeServerInitialMetadata, UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeServerTrailingMetadata, UnrefHeader);
-
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderNew);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+ RepresentativeClientInitialMetadata, OnInitialHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+ MoreRepresentativeClientInitialMetadata, OnInitialHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+ RepresentativeServerInitialMetadata, OnInitialHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderTimeout);
} // namespace hpack_parser_fixtures
diff --git a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
index 5a7a8d5baf..d4bd58b983 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
@@ -31,6 +31,8 @@ auto& force_library_initialization = Library::get();
* CONFIGURATIONS
*/
+// Replace "benchmark::internal::Benchmark" with "::testing::Benchmark" to use
+// internal microbenchmarking tooling
static void SweepSizesArgs(benchmark::internal::Benchmark* b) {
b->Args({0, 0});
for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h
index 9d70277fbc..d390ae08f6 100644
--- a/test/cpp/microbenchmarks/fullstack_fixtures.h
+++ b/test/cpp/microbenchmarks/fullstack_fixtures.h
@@ -48,6 +48,7 @@ namespace testing {
class FixtureConfiguration {
public:
+ virtual ~FixtureConfiguration() {}
virtual void ApplyCommonChannelArguments(ChannelArguments* c) const {
c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
diff --git a/test/cpp/microbenchmarks/helpers.h b/test/cpp/microbenchmarks/helpers.h
index 4aabd4094a..25d34b5f87 100644
--- a/test/cpp/microbenchmarks/helpers.h
+++ b/test/cpp/microbenchmarks/helpers.h
@@ -63,6 +63,7 @@ extern gpr_atm gpr_now_call_count;
class TrackCounters {
public:
TrackCounters() { grpc_stats_collect(&stats_begin_); }
+ virtual ~TrackCounters() {}
virtual void Finish(benchmark::State& state);
virtual void AddLabel(const grpc::string& label);
virtual void AddToLabel(std::ostream& out, benchmark::State& state);
diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
index 0251b2b392..228efef698 100644
--- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
+++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
@@ -16,10 +16,8 @@
FROM debian:jessie
-RUN apt-get update && apt-get install debian-keyring && apt-key update
-
# Install Git and basic packages.
-RUN apt-get update && apt-key update && apt-get install -y \
+RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
@@ -46,11 +44,6 @@ RUN apt-get update && apt-key update && apt-get install -y \
wget \
zip && apt-get clean
-# Install Node dependencies
-RUN touch .profile
-RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
-RUN /bin/bash -l -c "nvm install 8 && npm install -g node-pre-gyp"
-
##################
# Ruby dependencies
@@ -72,15 +65,8 @@ RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
# PHP dependencies
RUN apt-get update && apt-get install -y \
- php5 php5-dev php-pear phpunit
-
-##################
-# Install cross compiler for ARM
-
-RUN echo 'deb http://emdebian.org/tools/debian/ jessie main' | tee -a /etc/apt/sources.list.d/crosstools.list && \
- curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add -
+ php5 php5-dev php-pear phpunit && apt-get clean
-RUN dpkg --add-architecture armhf && apt-get update && apt-get install -y crossbuild-essential-armhf
RUN mkdir /var/local/jenkins
diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
index 2d179c8c45..d33e0f83ea 100644
--- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
+++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
@@ -16,10 +16,8 @@
FROM 32bit/debian:jessie
-RUN apt-get update && apt-get install debian-keyring && apt-key update
-
# Install Git and basic packages.
-RUN apt-get update && apt-key update && apt-get install -y \
+RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
@@ -46,11 +44,6 @@ RUN apt-get update && apt-key update && apt-get install -y \
wget \
zip && apt-get clean
-# Install Node dependencies
-RUN touch .profile
-RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
-RUN /bin/bash -l -c "nvm install 8 && npm install -g node-pre-gyp"
-
##################
# Ruby dependencies
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index a72390d9f8..c1bcdfd3d0 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1080,7 +1080,6 @@ src/core/lib/iomgr/error.h \
src/core/lib/iomgr/error_internal.h \
src/core/lib/iomgr/ev_epoll1_linux.h \
src/core/lib/iomgr/ev_epollex_linux.h \
-src/core/lib/iomgr/ev_epollsig_linux.h \
src/core/lib/iomgr/ev_poll_posix.h \
src/core/lib/iomgr/ev_posix.h \
src/core/lib/iomgr/exec_ctx.h \
@@ -1190,7 +1189,6 @@ src/cpp/client/secure_credentials.h \
src/cpp/codegen/codegen_init.cc \
src/cpp/common/alarm.cc \
src/cpp/common/auth_property_iterator.cc \
-src/cpp/common/callback_common.cc \
src/cpp/common/channel_arguments.cc \
src/cpp/common/channel_filter.cc \
src/cpp/common/channel_filter.h \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index aa75bc6828..0c2569d0d8 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -771,7 +771,10 @@ doc/compression_cookbook.md \
doc/connection-backoff-interop-test-description.md \
doc/connection-backoff.md \
doc/connectivity-semantics-and-api.md \
+doc/core/grpc-client-server-polling-engine-usage.md \
+doc/core/grpc-cq.md \
doc/core/grpc-error.md \
+doc/core/grpc-polling-engines.md \
doc/core/moving-to-c++.md \
doc/core/pending_api_cleanups.md \
doc/core/transport_explainer.md \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 7cd1dc7bf3..d9ab712301 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -771,7 +771,10 @@ doc/compression_cookbook.md \
doc/connection-backoff-interop-test-description.md \
doc/connection-backoff.md \
doc/connectivity-semantics-and-api.md \
+doc/core/grpc-client-server-polling-engine-usage.md \
+doc/core/grpc-cq.md \
doc/core/grpc-error.md \
+doc/core/grpc-polling-engines.md \
doc/core/moving-to-c++.md \
doc/core/pending_api_cleanups.md \
doc/core/transport_explainer.md \
@@ -1179,8 +1182,6 @@ src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epoll1_linux.h \
src/core/lib/iomgr/ev_epollex_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.h \
-src/core/lib/iomgr/ev_epollsig_linux.cc \
-src/core/lib/iomgr/ev_epollsig_linux.h \
src/core/lib/iomgr/ev_poll_posix.cc \
src/core/lib/iomgr/ev_poll_posix.h \
src/core/lib/iomgr/ev_posix.cc \
diff --git a/tools/internal_ci/helper_scripts/delete_nonartifacts.sh b/tools/internal_ci/helper_scripts/delete_nonartifacts.sh
index c7d6ba6d44..01e9427e1c 100755
--- a/tools/internal_ci/helper_scripts/delete_nonartifacts.sh
+++ b/tools/internal_ci/helper_scripts/delete_nonartifacts.sh
@@ -24,4 +24,4 @@ cd "$(dirname "$0")/../../.."
# after finishing each build. We only leave files we want to keep:
# - reports and artifacts
# - directory containing the kokoro scripts to prevent deleting a script while being executed.
-time find . -type f -not -iname "*sponge_log.xml" -not -path "./reports/*" -not -path "./artifacts/*" -not -path "./tools/internal_ci/*" -exec rm -f {} +
+time find . -type f -not -iname "*sponge_log.*" -not -path "./reports/*" -not -path "./artifacts/*" -not -path "./tools/internal_ci/*" -exec rm -f {} +
diff --git a/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg b/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
index 4a0badf43b..07f7f0c659 100644
--- a/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
+++ b/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg b/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
index a2cfe021e1..8f2813febf 100644
--- a/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
+++ b/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_basictests_multilang.cfg b/tools/internal_ci/linux/grpc_basictests_multilang.cfg
index 4433d14cd7..f8a5a4aea5 100644
--- a/tools/internal_ci/linux/grpc_basictests_multilang.cfg
+++ b/tools/internal_ci/linux/grpc_basictests_multilang.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_build_artifacts.cfg b/tools/internal_ci/linux/grpc_build_artifacts.cfg
index 88fc6b7b35..1e04a1e788 100644
--- a/tools/internal_ci/linux/grpc_build_artifacts.cfg
+++ b/tools/internal_ci/linux/grpc_build_artifacts.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_artifacts.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg b/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg
index 619e3ea3a9..2737e2f345 100644
--- a/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg
+++ b/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_artifacts_extra.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg b/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg
index 619e3ea3a9..2737e2f345 100644
--- a/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg
+++ b/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_artifacts_extra.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg b/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg
index 11c211fd2b..9a430db0f9 100644
--- a/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg
+++ b/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_submodule_at_head.sh"
timeout_mins: 180
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_build_packages.cfg b/tools/internal_ci/linux/grpc_build_packages.cfg
index 6a4a163dfc..23a676cf72 100644
--- a/tools/internal_ci/linux/grpc_build_packages.cfg
+++ b/tools/internal_ci/linux/grpc_build_packages.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_packages.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg b/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg
index 2f08e15e63..aef6a7a1dc 100644
--- a/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg
+++ b/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_submodule_at_head.sh"
timeout_mins: 180
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_coverage.cfg b/tools/internal_ci/linux/grpc_coverage.cfg
index 794a51d3f1..6eb37b7dec 100644
--- a/tools/internal_ci/linux/grpc_coverage.cfg
+++ b/tools/internal_ci/linux/grpc_coverage.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_coverage.sh"
timeout_mins: 420
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_distribtests.cfg b/tools/internal_ci/linux/grpc_distribtests.cfg
index 0f1d79355a..848d571333 100644
--- a/tools/internal_ci/linux/grpc_distribtests.cfg
+++ b/tools/internal_ci/linux/grpc_distribtests.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_distribtests.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_distribtests_standalone.cfg b/tools/internal_ci/linux/grpc_distribtests_standalone.cfg
index bc6c8e8f80..734bdfd78a 100644
--- a/tools/internal_ci/linux/grpc_distribtests_standalone.cfg
+++ b/tools/internal_ci/linux/grpc_distribtests_standalone.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_distribtests_standalone.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_full_performance_master.cfg b/tools/internal_ci/linux/grpc_full_performance_master.cfg
index 8852130a13..8ad93ee052 100644
--- a/tools/internal_ci/linux/grpc_full_performance_master.cfg
+++ b/tools/internal_ci/linux/grpc_full_performance_master.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_full_performance_master.sh"
timeout_mins: 600
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "**/perf_reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_full_performance_release.cfg b/tools/internal_ci/linux/grpc_full_performance_release.cfg
index e9a4bcdcaf..11a95e889f 100644
--- a/tools/internal_ci/linux/grpc_full_performance_release.cfg
+++ b/tools/internal_ci/linux/grpc_full_performance_release.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_full_performance_release.sh"
timeout_mins: 600
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "**/perf_reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop_alts.cfg b/tools/internal_ci/linux/grpc_interop_alts.cfg
index bda76faf44..4684aba96b 100644
--- a/tools/internal_ci/linux/grpc_interop_alts.cfg
+++ b/tools/internal_ci/linux/grpc_interop_alts.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop_matrix.cfg b/tools/internal_ci/linux/grpc_interop_matrix.cfg
index ae59e930f7..696a55c0df 100644
--- a/tools/internal_ci/linux/grpc_interop_matrix.cfg
+++ b/tools/internal_ci/linux/grpc_interop_matrix.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_interop_matrix.sh"
timeout_mins: 300
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
index 81f2fe9dec..9b35adcece 100644
--- a/tools/internal_ci/linux/grpc_interop_tocloud.cfg
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop_toprod.cfg b/tools/internal_ci/linux/grpc_interop_toprod.cfg
index 8dfc529947..de4db81e6b 100644
--- a/tools/internal_ci/linux/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/linux/grpc_interop_toprod.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_portability.cfg b/tools/internal_ci/linux/grpc_portability.cfg
index 76e5028477..f417f24bb1 100644
--- a/tools/internal_ci/linux/grpc_portability.cfg
+++ b/tools/internal_ci/linux/grpc_portability.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_portability_build_only.cfg b/tools/internal_ci/linux/grpc_portability_build_only.cfg
index 4acd9353fb..fab9dde3e5 100644
--- a/tools/internal_ci/linux/grpc_portability_build_only.cfg
+++ b/tools/internal_ci/linux/grpc_portability_build_only.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 180
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_publish_packages.cfg b/tools/internal_ci/linux/grpc_publish_packages.cfg
index 82d571d642..dc9fe7d0a7 100644
--- a/tools/internal_ci/linux/grpc_publish_packages.cfg
+++ b/tools/internal_ci/linux/grpc_publish_packages.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_publish_packages.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
index b20d2ffba8..704d5c6cbc 100644
--- a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
+++ b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 30
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_sanity.cfg b/tools/internal_ci/linux/grpc_sanity.cfg
index 9f65918e23..341471bbb5 100644
--- a/tools/internal_ci/linux/grpc_sanity.cfg
+++ b/tools/internal_ci/linux/grpc_sanity.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 40
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
index 8124f5c1b3..8a67d28ce4 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
index ecedc73e44..a681978b6e 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg
index 577cb28ae5..249ecc99ce 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg
index 9e0b724b2e..665d7f3d2c 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg
index 0fda74cf44..163274d4dc 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg
index 199a8905d9..b65cd3e05c 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
index f7e8d8ad33..59f38f0d1b 100644
--- a/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
index c1253b30f7..e91a612878 100644
--- a/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
index cb18e8e868..b1eb575605 100644
--- a/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
index d14c79a1f6..7321effc12 100644
--- a/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
- regex: "**/sponge_log.xml"
+ regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg b/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg
index 9269c345f0..47301d6141 100644
--- a/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_microbenchmark_diff.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_sanity.cfg b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
index 0f83299aab..276c34f0cf 100644
--- a/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 40
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg b/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg
index e86b3ab475..78358eac28 100644
--- a/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_trickle_diff.sh"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
index 06a4372ce2..d6d70677dd 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
index f875327c1b..7b22c6afef 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
index 6658a804d8..6c9dd6ef8d 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
index 957a91ef2b..8700c74c8d 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
index dbbfce90cb..02162d860b 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
index fb0cefa160..95582184ed 100644
--- a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
index 1daf7a514e..d444596a81 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
index a8503b7bcb..3891cc37e8 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
index 12af4581eb..91ce1627af 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
index 0d3803bf23..fcdc2de37b 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
index 557561810b..de2a74051b 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
index cb15ca34fd..51c291f7df 100644
--- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
+++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
@@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/grpc_basictests_dbg.cfg b/tools/internal_ci/macos/grpc_basictests_dbg.cfg
index 53bda1ff0a..e6f9c7ec87 100644
--- a/tools/internal_ci/macos/grpc_basictests_dbg.cfg
+++ b/tools/internal_ci/macos/grpc_basictests_dbg.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/grpc_basictests_opt.cfg b/tools/internal_ci/macos/grpc_basictests_opt.cfg
index d359eb601a..f2a83fe95a 100644
--- a/tools/internal_ci/macos/grpc_basictests_opt.cfg
+++ b/tools/internal_ci/macos/grpc_basictests_opt.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/grpc_build_artifacts.cfg b/tools/internal_ci/macos/grpc_build_artifacts.cfg
index 4da61faed3..c73cf4359f 100644
--- a/tools/internal_ci/macos/grpc_build_artifacts.cfg
+++ b/tools/internal_ci/macos/grpc_build_artifacts.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/macos/grpc_distribtests.cfg b/tools/internal_ci/macos/grpc_distribtests.cfg
index ae88f39b90..156ec6fe33 100644
--- a/tools/internal_ci/macos/grpc_distribtests.cfg
+++ b/tools/internal_ci/macos/grpc_distribtests.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/macos/grpc_interop.cfg b/tools/internal_ci/macos/grpc_interop.cfg
index b4b1b15cb4..434ecd19c4 100644
--- a/tools/internal_ci/macos/grpc_interop.cfg
+++ b/tools/internal_ci/macos/grpc_interop.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/grpc_interop_toprod.cfg b/tools/internal_ci/macos/grpc_interop_toprod.cfg
index c92c397daa..2cfc8a2d6d 100644
--- a/tools/internal_ci/macos/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/macos/grpc_interop_toprod.cfg
@@ -21,7 +21,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/interop/service_account/GrpcTes
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg b/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg
index 30c01d3e2f..c759397b78 100644
--- a/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg
+++ b/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg b/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg
index b63ee713bc..4d68341405 100644
--- a/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg
+++ b/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/macos/pull_request/grpc_interop.cfg b/tools/internal_ci/macos/pull_request/grpc_interop.cfg
index b4b1b15cb4..434ecd19c4 100644
--- a/tools/internal_ci/macos/pull_request/grpc_interop.cfg
+++ b/tools/internal_ci/macos/pull_request/grpc_interop.cfg
@@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
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 8942bc7ba7..fb215bdf99 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
@@ -20,7 +20,7 @@ timeout_mins: 60
gfile_resources: "/bigstore/grpc-testing-secrets/github_credentials/oauth_token.txt"
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/grpc_basictests.cfg b/tools/internal_ci/windows/grpc_basictests.cfg
index 8e644e4c5e..fcf5237bf3 100644
--- a/tools/internal_ci/windows/grpc_basictests.cfg
+++ b/tools/internal_ci/windows/grpc_basictests.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/grpc_basictests_dbg.cfg b/tools/internal_ci/windows/grpc_basictests_dbg.cfg
index 28d53cdc7b..4e5e7b6545 100644
--- a/tools/internal_ci/windows/grpc_basictests_dbg.cfg
+++ b/tools/internal_ci/windows/grpc_basictests_dbg.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/grpc_basictests_opt.cfg b/tools/internal_ci/windows/grpc_basictests_opt.cfg
index 4b7a965977..f5db6a9897 100644
--- a/tools/internal_ci/windows/grpc_basictests_opt.cfg
+++ b/tools/internal_ci/windows/grpc_basictests_opt.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/grpc_build_artifacts.cfg b/tools/internal_ci/windows/grpc_build_artifacts.cfg
index 38b0abd519..f45cfda121 100644
--- a/tools/internal_ci/windows/grpc_build_artifacts.cfg
+++ b/tools/internal_ci/windows/grpc_build_artifacts.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_build_artifacts.bat"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/windows/grpc_build_packages.cfg b/tools/internal_ci/windows/grpc_build_packages.cfg
index 65a8b1eef3..b351bbb11b 100644
--- a/tools/internal_ci/windows/grpc_build_packages.cfg
+++ b/tools/internal_ci/windows/grpc_build_packages.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_build_packages.bat"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/windows/grpc_distribtests.cfg b/tools/internal_ci/windows/grpc_distribtests.cfg
index 1766e601e5..e12d4bf98d 100644
--- a/tools/internal_ci/windows/grpc_distribtests.cfg
+++ b/tools/internal_ci/windows/grpc_distribtests.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_distribtests.bat"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/windows/grpc_distribtests_standalone.cfg b/tools/internal_ci/windows/grpc_distribtests_standalone.cfg
index 33a50fdc45..7f32ba4c70 100644
--- a/tools/internal_ci/windows/grpc_distribtests_standalone.cfg
+++ b/tools/internal_ci/windows/grpc_distribtests_standalone.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_distribtests_standalone.bat"
timeout_mins: 120
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}
diff --git a/tools/internal_ci/windows/grpc_portability.cfg b/tools/internal_ci/windows/grpc_portability.cfg
index 94e71753ef..aa86c06632 100644
--- a/tools/internal_ci/windows/grpc_portability.cfg
+++ b/tools/internal_ci/windows/grpc_portability.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/grpc_portability_build_only.cfg b/tools/internal_ci/windows/grpc_portability_build_only.cfg
index 3bc27f1f24..3dace627eb 100644
--- a/tools/internal_ci/windows/grpc_portability_build_only.cfg
+++ b/tools/internal_ci/windows/grpc_portability_build_only.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/pull_request/grpc_basictests.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests.cfg
index 91777cd7cb..a8e6f0675b 100644
--- a/tools/internal_ci/windows/pull_request/grpc_basictests.cfg
+++ b/tools/internal_ci/windows/pull_request/grpc_basictests.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg
index 81a1e9d3c8..ce957232fd 100644
--- a/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg
+++ b/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg
index 3bb6510ca7..7d2abbfb19 100644
--- a/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg
+++ b/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/windows/pull_request/grpc_portability.cfg b/tools/internal_ci/windows/pull_request/grpc_portability.cfg
index 2bda487629..6f332416fe 100644
--- a/tools/internal_ci/windows/pull_request/grpc_portability.cfg
+++ b/tools/internal_ci/windows/pull_request/grpc_portability.cfg
@@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat"
timeout_mins: 240
action {
define_artifacts {
- regex: "**/*sponge_log.xml"
+ regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index f3e93a0874..3df0ff58dc 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -493,23 +493,6 @@
"headers": [],
"is_filegroup": false,
"language": "c",
- "name": "ev_epollsig_linux_test",
- "src": [
- "test/core/iomgr/ev_epollsig_linux_test.cc"
- ],
- "third_party": false,
- "type": "target"
- },
- {
- "deps": [
- "gpr",
- "gpr_test_util",
- "grpc",
- "grpc_test_util"
- ],
- "headers": [],
- "is_filegroup": false,
- "language": "c",
"name": "fake_resolver_test",
"src": [
"test/core/client_channel/resolvers/fake_resolver_test.cc"
@@ -1863,23 +1846,6 @@
"headers": [],
"is_filegroup": false,
"language": "c",
- "name": "pollset_set_test",
- "src": [
- "test/core/iomgr/pollset_set_test.cc"
- ],
- "third_party": false,
- "type": "target"
- },
- {
- "deps": [
- "gpr",
- "gpr_test_util",
- "grpc",
- "grpc_test_util"
- ],
- "headers": [],
- "is_filegroup": false,
- "language": "c",
"name": "resolve_address_posix_test",
"src": [
"test/core/iomgr/resolve_address_posix_test.cc"
@@ -7126,19 +7092,6 @@
{
"deps": [
"gpr",
- "grpc"
- ],
- "headers": [],
- "is_filegroup": false,
- "language": "c",
- "name": "grpc_dll",
- "src": [],
- "third_party": false,
- "type": "lib"
- },
- {
- "deps": [
- "gpr",
"gpr_test_util",
"grpc",
"grpc_test_util_base"
@@ -9551,7 +9504,6 @@
"src/core/lib/iomgr/error.cc",
"src/core/lib/iomgr/ev_epoll1_linux.cc",
"src/core/lib/iomgr/ev_epollex_linux.cc",
- "src/core/lib/iomgr/ev_epollsig_linux.cc",
"src/core/lib/iomgr/ev_poll_posix.cc",
"src/core/lib/iomgr/ev_posix.cc",
"src/core/lib/iomgr/ev_windows.cc",
@@ -9732,7 +9684,6 @@
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
- "src/core/lib/iomgr/ev_epollsig_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
@@ -9884,7 +9835,6 @@
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
- "src/core/lib/iomgr/ev_epollsig_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
@@ -11470,7 +11420,6 @@
"src/cpp/client/credentials_cc.cc",
"src/cpp/client/generic_stub.cc",
"src/cpp/common/alarm.cc",
- "src/cpp/common/callback_common.cc",
"src/cpp/common/channel_arguments.cc",
"src/cpp/common/channel_filter.cc",
"src/cpp/common/channel_filter.h",
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index b3c07d9215..4fdd26efa4 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -605,26 +605,6 @@
"args": [],
"benchmark": false,
"ci_platforms": [
- "linux"
- ],
- "cpu_cost": 3,
- "exclude_configs": [],
- "exclude_iomgrs": [
- "uv"
- ],
- "flaky": false,
- "gtest": false,
- "language": "c",
- "name": "ev_epollsig_linux_test",
- "platforms": [
- "linux"
- ],
- "uses_polling": true
- },
- {
- "args": [],
- "benchmark": false,
- "ci_platforms": [
"linux",
"mac",
"posix",
@@ -2105,26 +2085,6 @@
"args": [],
"benchmark": false,
"ci_platforms": [
- "linux"
- ],
- "cpu_cost": 1.0,
- "exclude_configs": [],
- "exclude_iomgrs": [
- "uv"
- ],
- "flaky": false,
- "gtest": false,
- "language": "c",
- "name": "pollset_set_test",
- "platforms": [
- "linux"
- ],
- "uses_polling": true
- },
- {
- "args": [],
- "benchmark": false,
- "ci_platforms": [
"linux",
"mac",
"posix"
diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py
index 561f453da7..b732e1e03e 100755
--- a/tools/run_tests/python_utils/jobset.py
+++ b/tools/run_tests/python_utils/jobset.py
@@ -176,13 +176,15 @@ class JobSpec(object):
timeout_retries=0,
kill_handler=None,
cpu_cost=1.0,
- verbose_success=False):
+ verbose_success=False,
+ logfilename=None):
"""
Arguments:
cmdline: a list of arguments to pass as the command line
environ: a dictionary of environment variables to set in the child process
kill_handler: a handler that will be called whenever job.kill() is invoked
cpu_cost: number of cores per second this job needs
+ logfilename: use given file to store job's output, rather than using a temporary file
"""
if environ is None:
environ = {}
@@ -197,6 +199,11 @@ class JobSpec(object):
self.kill_handler = kill_handler
self.cpu_cost = cpu_cost
self.verbose_success = verbose_success
+ self.logfilename = logfilename
+ if self.logfilename and self.flake_retries != 0 and self.timeout_retries != 0:
+ # Forbidden to avoid overwriting the test log when retrying.
+ raise Exception(
+ 'Cannot use custom logfile when retries are enabled')
def identity(self):
return '%r %r' % (self.cmdline, self.environ)
@@ -261,7 +268,15 @@ class Job(object):
return self._spec
def start(self):
- self._tempfile = tempfile.TemporaryFile()
+ if self._spec.logfilename:
+ # make sure the log directory exists
+ logfile_dir = os.path.dirname(
+ os.path.abspath(self._spec.logfilename))
+ if not os.path.exists(logfile_dir):
+ os.makedirs(logfile_dir)
+ self._logfile = open(self._spec.logfilename, 'w+')
+ else:
+ self._logfile = tempfile.TemporaryFile()
env = dict(os.environ)
env.update(self._spec.environ)
env.update(self._add_env)
@@ -277,7 +292,7 @@ class Job(object):
measure_cpu_costs = False
try_start = lambda: subprocess.Popen(args=cmdline,
stderr=subprocess.STDOUT,
- stdout=self._tempfile,
+ stdout=self._logfile,
cwd=self._spec.cwd,
shell=self._spec.shell,
env=env)
@@ -300,7 +315,7 @@ class Job(object):
"""Poll current state of the job. Prints messages at completion."""
def stdout(self=self):
- stdout = read_from_start(self._tempfile)
+ stdout = read_from_start(self._logfile)
self.result.message = stdout[-_MAX_RESULT_SIZE:]
return stdout
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 9bbc2e3e0e..e8d6b59687 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -777,12 +777,14 @@ def cloud_to_prod_jobspec(language,
]
if transport_security == 'tls':
transport_security_options = ['--use_tls=true']
- elif transport_security == 'google_default_credentials' and language == 'c++':
+ elif transport_security == 'google_default_credentials' and str(
+ language) in ['c++', 'go']:
transport_security_options = [
'--custom_credentials_type=google_default_credentials'
]
else:
- print('Invalid transport security option.')
+ print('Invalid transport security option %s in cloud_to_prod_jobspec.' %
+ transport_security)
sys.exit(1)
cmdargs = cmdargs + transport_security_options
environ = dict(language.cloud_to_prod_env(), **language.global_env())
@@ -817,8 +819,9 @@ def cloud_to_prod_jobspec(language,
cmdline=cmdline,
cwd=cwd,
environ=environ,
- shortname='%s:%s:%s:%s' % (suite_name, language, server_host_nickname,
- test_case),
+ shortname='%s:%s:%s:%s:%s' %
+ (suite_name, language, server_host_nickname, test_case,
+ transport_security),
timeout_seconds=_TEST_TIMEOUT,
flake_retries=4 if args.allow_flakes else 0,
timeout_retries=2 if args.allow_flakes else 0,
@@ -848,7 +851,8 @@ def cloud_to_cloud_jobspec(language,
elif transport_security == 'insecure':
interop_only_options += ['--use_tls=false']
else:
- print('Invalid transport security option.')
+ print('Invalid transport security option %s in cloud_to_cloud_jobspec.'
+ % transport_security)
sys.exit(1)
client_test_case = test_case
@@ -903,8 +907,8 @@ def cloud_to_cloud_jobspec(language,
cmdline=cmdline,
cwd=cwd,
environ=environ,
- shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name,
- test_case),
+ shortname='cloud_to_cloud:%s:%s_server:%s:%s' %
+ (language, server_name, test_case, transport_security),
timeout_seconds=_TEST_TIMEOUT,
flake_retries=4 if args.allow_flakes else 0,
timeout_retries=2 if args.allow_flakes else 0,
@@ -929,7 +933,8 @@ def server_jobspec(language,
elif transport_security == 'insecure':
server_cmd += ['--use_tls=false']
else:
- print('Invalid transport security option.')
+ print('Invalid transport security option %s in server_jobspec.' %
+ transport_security)
sys.exit(1)
cmdline = bash_cmdline(language.server_cmd(server_cmd))
environ = language.global_env()
@@ -1318,7 +1323,7 @@ try:
service_account_key_file,
transport_security='tls')
jobs.append(tls_test_job)
- if language == 'c++':
+ if str(language) in ['c++', 'go']:
google_default_creds_test_job = cloud_to_prod_jobspec(
language,
test_case,
@@ -1370,7 +1375,9 @@ try:
service_account_key_file,
transport_security='tls')
jobs.append(tls_test_job)
- if language == 'c++':
+ if str(language) in [
+ 'go'
+ ]: # Add more languages to the list to turn on tests.
google_default_creds_test_job = cloud_to_prod_jobspec(
language,
test_case,
@@ -1378,6 +1385,7 @@ try:
prod_servers[server_host_nickname],
docker_image=docker_images.get(
str(language)),
+ auth=True,
manual_cmd_log=client_manual_cmd_log,
service_account_key_file=args.
service_account_key_file,
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index ecb5e1d899..3d73f9ec0e 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -61,7 +61,7 @@ _FORCE_ENVIRON_FOR_WRAPPERS = {
}
_POLLING_STRATEGIES = {
- 'linux': ['epollex', 'epollsig', 'epoll1', 'poll', 'poll-cv'],
+ 'linux': ['epollex', 'epoll1', 'poll', 'poll-cv'],
'mac': ['poll'],
}
@@ -1430,7 +1430,7 @@ argp.add_argument(
default=None,
type=str,
help='Only use the specified comma-delimited list of polling engines. '
- 'Example: --force_use_pollers epollsig,poll '
+ 'Example: --force_use_pollers epoll1,poll '
' (This flag has no effect if --force_default_poller flag is also used)')
argp.add_argument(
'--max_time', default=-1, type=int, help='Maximum test runtime in seconds')
diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py
index 1bbec94ee1..00fc68ad17 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -43,9 +43,6 @@ _OBJC_RUNTESTS_TIMEOUT = 90 * 60
# Number of jobs assigned to each run_tests.py instance
_DEFAULT_INNER_JOBS = 2
-# report suffix is important for reports to get picked up by internal CI
-_REPORT_SUFFIX = 'sponge_log.xml'
-
def _safe_report_name(name):
"""Reports with '+' in target name won't show correctly in ResultStore"""
@@ -54,7 +51,15 @@ def _safe_report_name(name):
def _report_filename(name):
"""Generates report file name with directory structure that leads to better presentation by internal CI"""
- return '%s/%s' % (_safe_report_name(name), _REPORT_SUFFIX)
+ # 'sponge_log.xml' suffix must be there for results to get recognized by kokoro.
+ return '%s/%s' % (_safe_report_name(name), 'sponge_log.xml')
+
+
+def _report_logfilename(name):
+ """Generates log file name that corresponds to name generated by _report_filename"""
+ # 'sponge_log.log' suffix must be there for log to get recognized as "target log"
+ # for the corresponding 'sponge_log.xml' report.
+ return '%s/%s' % (_safe_report_name(name), 'sponge_log.log')
def _docker_jobspec(name,
@@ -75,7 +80,8 @@ def _docker_jobspec(name,
] + runtests_args,
environ=runtests_envs,
shortname='run_tests_%s' % name,
- timeout_seconds=timeout_seconds)
+ timeout_seconds=timeout_seconds,
+ logfilename=_report_logfilename(name))
return test_job
@@ -102,7 +108,8 @@ def _workspace_jobspec(name,
] + runtests_args,
environ=env,
shortname='run_tests_%s' % name,
- timeout_seconds=timeout_seconds)
+ timeout_seconds=timeout_seconds,
+ logfilename=_report_logfilename(name))
return test_job