Merge pull request #10407 from kpayson64/alpine_linux_support
Alpine linux support
diff --git a/BUILD b/BUILD
index c4632fc..1991c86 100644
--- a/BUILD
+++ b/BUILD
@@ -41,7 +41,7 @@
core_version = "3.0.0-dev"
-version = "1.2.0"
+version = "1.3.0-dev"
grpc_cc_library(
name = "gpr",
@@ -67,6 +67,7 @@
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
+ "grpc_max_age_filter",
"grpc_resolver_dns_ares",
"grpc_resolver_dns_native",
"grpc_resolver_sockaddr",
@@ -75,7 +76,6 @@
"grpc_transport_chttp2_client_secure",
"grpc_transport_chttp2_server_insecure",
"grpc_transport_chttp2_server_secure",
- "grpc_max_age_filter",
],
)
@@ -109,11 +109,11 @@
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
+ "grpc_max_age_filter",
"grpc_resolver_dns_native",
"grpc_resolver_sockaddr",
"grpc_transport_chttp2_client_insecure",
"grpc_transport_chttp2_server_insecure",
- "grpc_max_age_filter",
],
)
@@ -177,8 +177,6 @@
],
hdrs = [
"src/compiler/config.h",
- "src/compiler/schema_interface.h",
- "src/compiler/protobuf_plugin.h",
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h",
"src/compiler/csharp_generator.h",
@@ -190,6 +188,7 @@
"src/compiler/objective_c_generator_helpers.h",
"src/compiler/php_generator.h",
"src/compiler/php_generator_helpers.h",
+ "src/compiler/protobuf_plugin.h",
"src/compiler/python_generator.h",
"src/compiler/python_generator_helpers.h",
"src/compiler/python_private_generator.h",
@@ -197,6 +196,7 @@
"src/compiler/ruby_generator_helpers-inl.h",
"src/compiler/ruby_generator_map-inl.h",
"src/compiler/ruby_generator_string-inl.h",
+ "src/compiler/schema_interface.h",
],
external_deps = [
"protobuf_clib",
@@ -884,14 +884,14 @@
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h",
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h",
],
+ external_deps = [
+ "cares",
+ ],
language = "c",
deps = [
"grpc_base",
"grpc_client_channel",
],
- external_deps = [
- "cares",
- ],
)
grpc_cc_library(
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6c376ef..1fcd2d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,9 +5,6 @@
# This file can be regenerated from the template by running
# tools/buildgen/generate_projects.sh
#
-# Additionally, this is currently very experimental, and unsupported.
-# Further work will happen on that file.
-#
# Copyright 2015, Google Inc.
# All rights reserved.
#
@@ -308,7 +305,7 @@
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
- file(RELATIVE_PATH REL_FIL ${CMAKE_SOURCE_DIR} ${ABS_FIL})
+ file(RELATIVE_PATH REL_FIL ${CMAKE_CURRENT_SOURCE_DIR} ${ABS_FIL})
get_filename_component(REL_DIR ${REL_FIL} DIRECTORY)
set(RELFIL_WE "${REL_DIR}/${FIL_WE}")
@@ -324,7 +321,7 @@
${_protobuf_include_path}
${REL_FIL}
DEPENDS ${ABS_FIL} ${_gRPC_PROTOBUF_PROTOC} grpc_cpp_plugin
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}"
VERBATIM)
@@ -626,6 +623,9 @@
add_dependencies(buildtests_cxx bm_cq)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_cq_multiple_threads)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_error)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -8979,6 +8979,49 @@
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_executable(bm_cq_multiple_threads
+ test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
+ third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_cq_multiple_threads
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${BORINGSSL_ROOT_DIR}/include
+ PRIVATE ${PROTOBUF_ROOT_DIR}/src
+ PRIVATE ${BENCHMARK_ROOT_DIR}/include
+ PRIVATE ${ZLIB_ROOT_DIR}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+ PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+ PRIVATE ${CARES_INCLUDE_DIR}
+ PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+ PRIVATE third_party/googletest/include
+ PRIVATE third_party/googletest
+ PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_cq_multiple_threads
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_benchmark
+ benchmark
+ grpc++_test_util
+ grpc_test_util
+ grpc++
+ grpc
+ gpr_test_util
+ gpr
+ ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
add_executable(bm_error
test/cpp/microbenchmarks/bm_error.cc
third_party/googletest/googletest/src/gtest-all.cc
diff --git a/Makefile b/Makefile
index 5070c1d..40b82e6 100644
--- a/Makefile
+++ b/Makefile
@@ -1105,6 +1105,7 @@
bm_chttp2_transport: $(BINDIR)/$(CONFIG)/bm_chttp2_transport
bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
bm_cq: $(BINDIR)/$(CONFIG)/bm_cq
+bm_cq_multiple_threads: $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads
bm_error: $(BINDIR)/$(CONFIG)/bm_error
bm_fullstack_streaming_ping_pong: $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong
bm_fullstack_streaming_pump: $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump
@@ -1530,6 +1531,7 @@
$(BINDIR)/$(CONFIG)/bm_chttp2_transport \
$(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_cq \
+ $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads \
$(BINDIR)/$(CONFIG)/bm_error \
$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong \
$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump \
@@ -1648,6 +1650,7 @@
$(BINDIR)/$(CONFIG)/bm_chttp2_transport \
$(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_cq \
+ $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads \
$(BINDIR)/$(CONFIG)/bm_error \
$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong \
$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump \
@@ -1997,6 +2000,8 @@
$(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 )
$(E) "[RUN] Testing bm_cq"
$(Q) $(BINDIR)/$(CONFIG)/bm_cq || ( echo test bm_cq failed ; exit 1 )
+ $(E) "[RUN] Testing bm_cq_multiple_threads"
+ $(Q) $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads || ( echo test bm_cq_multiple_threads failed ; exit 1 )
$(E) "[RUN] Testing bm_error"
$(Q) $(BINDIR)/$(CONFIG)/bm_error || ( echo test bm_error failed ; exit 1 )
$(E) "[RUN] Testing bm_fullstack_streaming_ping_pong"
@@ -2383,12 +2388,12 @@
$(GENDIR)/src/proto/grpc/testing/services.pb.cc: protoc_dep_error
$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: protoc_dep_error
else
-$(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc
+$(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
-$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc
+$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
@@ -13360,6 +13365,50 @@
endif
+BM_CQ_MULTIPLE_THREADS_SRC = \
+ test/cpp/microbenchmarks/bm_cq_multiple_threads.cc \
+
+BM_CQ_MULTIPLE_THREADS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CQ_MULTIPLE_THREADS_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: $(PROTOBUF_DEP) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads
+
+endif
+
+endif
+
+$(BM_CQ_MULTIPLE_THREADS_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq_multiple_threads.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_cq_multiple_threads: $(BM_CQ_MULTIPLE_THREADS_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_CQ_MULTIPLE_THREADS_OBJS:.o=.dep)
+endif
+endif
+
+
BM_ERROR_SRC = \
test/cpp/microbenchmarks/bm_error.cc \
diff --git a/build.yaml b/build.yaml
index c294fc9..6fbc8d9 100644
--- a/build.yaml
+++ b/build.yaml
@@ -3217,6 +3217,27 @@
- mac
- linux
- posix
+- name: bm_cq_multiple_threads
+ build: test
+ language: c++
+ src:
+ - test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
+ deps:
+ - grpc_benchmark
+ - benchmark
+ - grpc++_test_util
+ - grpc_test_util
+ - grpc++
+ - grpc
+ - gpr_test_util
+ - gpr
+ args:
+ - --benchmark_min_time=0
+ defaults: benchmark
+ platforms:
+ - mac
+ - linux
+ - posix
- name: bm_error
build: test
language: c++
diff --git a/cmake/msvc_static_runtime.cmake b/cmake/msvc_static_runtime.cmake
index 5a31ab3..fc6d1d6 100644
--- a/cmake/msvc_static_runtime.cmake
+++ b/cmake/msvc_static_runtime.cmake
@@ -3,6 +3,8 @@
if(gRPC_MSVC_STATIC_RUNTIME)
# switch from dynamic to static linking of msvcrt
foreach(flag_var
+ CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+ CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md
index 5f01af3..6bb2808 100644
--- a/doc/PROTOCOL-WEB.md
+++ b/doc/PROTOCOL-WEB.md
@@ -83,7 +83,8 @@
User Agent
-* U-A: grpc-web-javascript
+* Do NOT use User-Agent header (which is to be set by browsers, by default)
+* Use X-User-Agent: grpc-web-javascript/0.1 (follow the same format as specified in [gRPC over HTTP2](http://www.grpc.io/docs/guides/wire.html))
---
diff --git a/etc/roots.pem b/etc/roots.pem
index 6660567..b2096fb 100644
--- a/etc/roots.pem
+++ b/etc/roots.pem
@@ -1617,42 +1617,6 @@
pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
-----END CERTIFICATE-----
-# Issuer: CN=WellsSecure Public Root Certificate Authority O=Wells Fargo WellsSecure OU=Wells Fargo Bank NA
-# Subject: CN=WellsSecure Public Root Certificate Authority O=Wells Fargo WellsSecure OU=Wells Fargo Bank NA
-# Label: "WellsSecure Public Root Certificate Authority"
-# Serial: 1
-# MD5 Fingerprint: 15:ac:a5:c2:92:2d:79:bc:e8:7f:cb:67:ed:02:cf:36
-# SHA1 Fingerprint: e7:b4:f6:9d:61:ec:90:69:db:7e:90:a7:40:1a:3c:f4:7d:4f:e8:ee
-# SHA256 Fingerprint: a7:12:72:ae:aa:a3:cf:e8:72:7f:7f:b3:9f:0f:b3:d1:e5:42:6e:90:60:b0:6e:e6:f1:3e:9a:3c:58:33:cd:43
------BEGIN CERTIFICATE-----
-MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx
-IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs
-cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v
-dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0
-MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl
-bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD
-DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r
-WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU
-Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs
-HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj
-z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf
-SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl
-AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG
-KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P
-AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j
-BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC
-VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX
-ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
-Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB
-ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd
-/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB
-A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn
-k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9
-iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv
-2G0xffX8oRAHh84vWdw+WNs=
------END CERTIFICATE-----
-
# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
# Label: "COMODO ECC Certification Authority"
@@ -1738,57 +1702,6 @@
/L7fCg0=
-----END CERTIFICATE-----
-# Issuer: CN=Microsec e-Szigno Root CA O=Microsec Ltd. OU=e-Szigno CA
-# Subject: CN=Microsec e-Szigno Root CA O=Microsec Ltd. OU=e-Szigno CA
-# Label: "Microsec e-Szigno Root CA"
-# Serial: 272122594155480254301341951808045322001
-# MD5 Fingerprint: f0:96:b6:2f:c5:10:d5:67:8e:83:25:32:e8:5e:2e:e5
-# SHA1 Fingerprint: 23:88:c9:d3:71:cc:9e:96:3d:ff:7d:3c:a7:ce:fc:d6:25:ec:19:0d
-# SHA256 Fingerprint: 32:7a:3d:76:1a:ba:de:a0:34:eb:99:84:06:27:5c:b1:a4:77:6e:fd:ae:2f:df:6d:01:68:ea:1c:4f:55:67:d0
------BEGIN CERTIFICATE-----
-MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw
-cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy
-b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z
-ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4
-NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN
-TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p
-Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u
-uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+
-LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA
-vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770
-Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx
-62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB
-AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw
-LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP
-BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB
-AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov
-MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5
-ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
-AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT
-AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh
-ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo
-AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa
-AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln
-bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p
-Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP
-PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv
-Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB
-EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu
-w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj
-cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV
-HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI
-VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS
-BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS
-b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS
-8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds
-ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl
-7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
-86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR
-hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/
-MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
------END CERTIFICATE-----
-
# Issuer: CN=Certigna O=Dhimyotis
# Subject: CN=Certigna O=Dhimyotis
# Label: "Certigna"
@@ -2014,36 +1927,6 @@
2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE=
-----END CERTIFICATE-----
-# Issuer: O=Japanese Government OU=ApplicationCA
-# Subject: O=Japanese Government OU=ApplicationCA
-# Label: "ApplicationCA - Japanese Government"
-# Serial: 49
-# MD5 Fingerprint: 7e:23:4e:5b:a7:a5:b4:25:e9:00:07:74:11:62:ae:d6
-# SHA1 Fingerprint: 7f:8a:b0:cf:d0:51:87:6a:66:f3:36:0f:47:c8:8d:8c:d3:35:fc:74
-# SHA256 Fingerprint: 2d:47:43:7d:e1:79:51:21:5a:12:f3:c5:8e:51:c7:29:a5:80:26:ef:1f:cc:0a:5f:b3:d9:dc:01:2f:60:0d:19
------BEGIN CERTIFICATE-----
-MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc
-MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp
-b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT
-AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs
-aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H
-j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K
-f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55
-IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw
-FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht
-QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm
-/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ
-k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ
-MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC
-seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ
-hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+
-eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U
-DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj
-B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
-rosot4LKGAfmt1t06SAZf7IbiVQ=
------END CERTIFICATE-----
-
# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
# Label: "GeoTrust Primary Certification Authority - G3"
@@ -4720,39 +4603,6 @@
+qtB4Uu2NQvAmxU=
-----END CERTIFICATE-----
-# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6 O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
-# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6 O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
-# Label: "TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6"
-# Serial: 138134509972618
-# MD5 Fingerprint: f8:c5:ee:2a:6b:be:95:8d:08:f7:25:4a:ea:71:3e:46
-# SHA1 Fingerprint: 8a:5c:8c:ee:a5:03:e6:05:56:ba:d8:1b:d4:f6:c9:b0:ed:e5:2f:e0
-# SHA256 Fingerprint: 8d:e7:86:55:e1:be:7f:78:47:80:0b:93:f6:94:d2:1d:36:8c:c0:6e:03:3e:7f:ab:04:bb:5e:b9:9d:a6:b7:00
------BEGIN CERTIFICATE-----
-MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQG
-EwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdp
-IMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBB
-LsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBI
-aXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5MDQxMFoXDTIzMTIx
-NjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBLBgNV
-BAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2
-ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVs
-ZWt0cm9uaWsgU2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdsGjW6L0UlqMACprx9MfMkU1x
-eHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a2uqsxgbPJQ1BgfbBOCK9
-+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EEDwnS3/faA
-z1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0p
-u5FbHH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6p
-lVxiSvgNZ1GpryHV+DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMB
-AAGjQjBAMB0GA1UdDgQWBBTdVRcT9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8E
-BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAb1gNl0Oq
-FlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3RfdCaqaXKGDsC
-QC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy
-o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKID
-gI6tflEATseWhvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm
-9ocJV612ph1jmv3XZch4gyt1O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsG
-tAuYSyher4hYyw==
------END CERTIFICATE-----
-
# Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
# Label: "Certinomis - Root CA"
@@ -5402,3 +5252,37 @@
x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6
oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
-----END CERTIFICATE-----
+
+# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM
+# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM
+# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1"
+# Serial: 1
+# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49
+# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca
+# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
diff --git a/grpc.gemspec b/grpc.gemspec
index a3a5870..6a20468 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -24,7 +24,7 @@
s.files += Dir.glob('include/grpc/**/*')
s.test_files = Dir.glob('src/ruby/spec/**/*')
s.bindir = 'src/ruby/bin'
- s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
+ s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.1'
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index be6857c..dd63c21 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -63,21 +63,31 @@
class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
+const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin";
+
// TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen.
inline grpc_metadata* FillMetadataArray(
- const std::multimap<grpc::string, grpc::string>& metadata) {
- if (metadata.empty()) {
+ const std::multimap<grpc::string, grpc::string>& metadata,
+ size_t* metadata_count, const grpc::string& optional_error_details) {
+ *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1);
+ if (*metadata_count == 0) {
return nullptr;
}
grpc_metadata* metadata_array =
(grpc_metadata*)(g_core_codegen_interface->gpr_malloc(
- metadata.size() * sizeof(grpc_metadata)));
+ (*metadata_count) * sizeof(grpc_metadata)));
size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
metadata_array[i].key = SliceReferencingString(iter->first);
metadata_array[i].value = SliceReferencingString(iter->second);
}
+ if (!optional_error_details.empty()) {
+ metadata_array[i].key =
+ g_core_codegen_interface->grpc_slice_from_static_buffer(
+ kBinaryErrorDetailsKey, sizeof(kBinaryErrorDetailsKey) - 1);
+ metadata_array[i].value = SliceReferencingString(optional_error_details);
+ }
return metadata_array;
}
@@ -216,8 +226,8 @@
maybe_compression_level_.is_set = false;
send_ = true;
flags_ = flags;
- initial_metadata_count_ = metadata.size();
- initial_metadata_ = FillMetadataArray(metadata);
+ initial_metadata_ =
+ FillMetadataArray(metadata, &initial_metadata_count_, "");
}
void set_compression_level(grpc_compression_level level) {
@@ -454,11 +464,12 @@
void ServerSendStatus(
const std::multimap<grpc::string, grpc::string>& trailing_metadata,
const Status& status) {
- trailing_metadata_count_ = trailing_metadata.size();
- trailing_metadata_ = FillMetadataArray(trailing_metadata);
+ send_error_details_ = status.error_details();
+ trailing_metadata_ = FillMetadataArray(
+ trailing_metadata, &trailing_metadata_count_, send_error_details_);
send_status_available_ = true;
send_status_code_ = static_cast<grpc_status_code>(GetCanonicalCode(status));
- send_status_details_ = status.error_message();
+ send_error_message_ = status.error_message();
}
protected:
@@ -470,9 +481,9 @@
trailing_metadata_count_;
op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
op->data.send_status_from_server.status = send_status_code_;
- status_details_slice_ = SliceReferencingString(send_status_details_);
+ error_message_slice_ = SliceReferencingString(send_error_message_);
op->data.send_status_from_server.status_details =
- send_status_details_.empty() ? nullptr : &status_details_slice_;
+ send_error_message_.empty() ? nullptr : &error_message_slice_;
op->flags = 0;
op->reserved = NULL;
}
@@ -486,10 +497,11 @@
private:
bool send_status_available_;
grpc_status_code send_status_code_;
- grpc::string send_status_details_;
+ grpc::string send_error_details_;
+ grpc::string send_error_message_;
size_t trailing_metadata_count_;
grpc_metadata* trailing_metadata_;
- grpc_slice status_details_slice_;
+ grpc_slice error_message_slice_;
};
class CallOpRecvInitialMetadata {
@@ -528,7 +540,7 @@
void ClientRecvStatus(ClientContext* context, Status* status) {
metadata_map_ = &context->trailing_metadata_;
recv_status_ = status;
- status_details_ = g_core_codegen_interface->grpc_empty_slice();
+ error_message_ = g_core_codegen_interface->grpc_empty_slice();
}
protected:
@@ -538,7 +550,7 @@
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
op->data.recv_status_on_client.status = &status_code_;
- op->data.recv_status_on_client.status_details = &status_details_;
+ op->data.recv_status_on_client.status_details = &error_message_;
op->flags = 0;
op->reserved = NULL;
}
@@ -546,10 +558,17 @@
void FinishOp(bool* status) {
if (recv_status_ == nullptr) return;
metadata_map_->FillMap();
+ grpc::string binary_error_details;
+ auto iter = metadata_map_->map()->find(kBinaryErrorDetailsKey);
+ if (iter != metadata_map_->map()->end()) {
+ binary_error_details =
+ grpc::string(iter->second.begin(), iter->second.length());
+ }
*recv_status_ = Status(static_cast<StatusCode>(status_code_),
- grpc::string(GRPC_SLICE_START_PTR(status_details_),
- GRPC_SLICE_END_PTR(status_details_)));
- g_core_codegen_interface->grpc_slice_unref(status_details_);
+ grpc::string(GRPC_SLICE_START_PTR(error_message_),
+ GRPC_SLICE_END_PTR(error_message_)),
+ binary_error_details);
+ g_core_codegen_interface->grpc_slice_unref(error_message_);
recv_status_ = nullptr;
}
@@ -557,7 +576,7 @@
MetadataMap* metadata_map_;
Status* recv_status_;
grpc_status_code status_code_;
- grpc_slice status_details_;
+ grpc_slice error_message_;
};
/// An abstract collection of CallOpSet's, to be used whenever
diff --git a/include/grpc++/impl/codegen/status.h b/include/grpc++/impl/codegen/status.h
index a509d31..5cce3c1 100644
--- a/include/grpc++/impl/codegen/status.h
+++ b/include/grpc++/impl/codegen/status.h
@@ -47,10 +47,16 @@
/// Construct an OK instance.
Status() : code_(StatusCode::OK) {}
- /// Construct an instance with associated \a code and \a details (also
- // referred to as "error_message").
- Status(StatusCode code, const grpc::string& details)
- : code_(code), details_(details) {}
+ /// Construct an instance with associated \a code and \a error_message
+ Status(StatusCode code, const grpc::string& error_message)
+ : code_(code), error_message_(error_message) {}
+
+ /// Construct an instance with \a code, \a error_message and \a error_details
+ Status(StatusCode code, const grpc::string& error_message,
+ const grpc::string error_details)
+ : code_(code),
+ error_message_(error_message),
+ binary_error_details_(error_details) {}
// Pre-defined special status objects.
/// An OK pre-defined instance.
@@ -61,14 +67,18 @@
/// Return the instance's error code.
StatusCode error_code() const { return code_; }
/// Return the instance's error message.
- grpc::string error_message() const { return details_; }
+ grpc::string error_message() const { return error_message_; }
+ /// Return the (binary) error details.
+ // Usually it contains a serialized google.rpc.Status proto.
+ grpc::string error_details() const { return binary_error_details_; }
/// Is the status OK?
bool ok() const { return code_ == StatusCode::OK; }
private:
StatusCode code_;
- grpc::string details_;
+ grpc::string error_message_;
+ grpc::string binary_error_details_;
};
} // namespace grpc
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 8a8b206..fdedf0a 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -271,6 +271,14 @@
* possible. */
#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \
"grpc.use_cronet_packet_coalescing"
+/* Channel arg (integer) setting how large a slice to try and read from the wire
+each time recvmsg (or equivalent) is called */
+#define GRPC_ARG_TCP_READ_CHUNK_SIZE "grpc.experimental.tcp_read_chunk_size"
+#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192
+#define GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE \
+ "grpc.experimental.tcp_min_read_chunk_size"
+#define GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE \
+ "grpc.experimental.tcp_max_read_chunk_size"
/** \} */
/** Result of a grpc call. If the caller satisfies the prerequisites of a
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
index f46e849..6ab176e 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
@@ -57,12 +57,9 @@
char *name;
gpr_asprintf(&name, "fd:%d", fd);
- grpc_resource_quota *resource_quota = grpc_resource_quota_from_channel_args(
- grpc_server_get_channel_args(server));
grpc_endpoint *server_endpoint =
- grpc_tcp_create(grpc_fd_create(fd, name), resource_quota,
- GRPC_TCP_DEFAULT_READ_SLICE_SIZE, name);
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
+ grpc_tcp_create(&exec_ctx, grpc_fd_create(fd, name),
+ grpc_server_get_channel_args(server), name);
gpr_free(name);
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index fc33834..9eab136 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -47,7 +47,7 @@
typedef struct {
grpc_channel_security_connector base;
- tsi_ssl_handshaker_factory *handshaker_factory;
+ tsi_ssl_client_handshaker_factory *handshaker_factory;
char *secure_peer_name;
} grpc_httpcli_ssl_channel_security_connector;
@@ -56,7 +56,7 @@
grpc_httpcli_ssl_channel_security_connector *c =
(grpc_httpcli_ssl_channel_security_connector *)sc;
if (c->handshaker_factory != NULL) {
- tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
+ tsi_ssl_client_handshaker_factory_destroy(c->handshaker_factory);
}
if (c->secure_peer_name != NULL) gpr_free(c->secure_peer_name);
gpr_free(sc);
@@ -69,7 +69,7 @@
(grpc_httpcli_ssl_channel_security_connector *)sc;
tsi_handshaker *handshaker = NULL;
if (c->handshaker_factory != NULL) {
- tsi_result result = tsi_ssl_handshaker_factory_create_handshaker(
+ tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
c->handshaker_factory, c->secure_peer_name, &handshaker);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
diff --git a/src/core/lib/iomgr/endpoint_pair.h b/src/core/lib/iomgr/endpoint_pair.h
index f9de0c7..6407a6a 100644
--- a/src/core/lib/iomgr/endpoint_pair.h
+++ b/src/core/lib/iomgr/endpoint_pair.h
@@ -41,8 +41,7 @@
grpc_endpoint *server;
} grpc_endpoint_pair;
-grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(
- const char *name, grpc_resource_quota *resource_quota,
- size_t read_slice_size);
+grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
+ grpc_channel_args *args);
#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H */
diff --git a/src/core/lib/iomgr/endpoint_pair_posix.c b/src/core/lib/iomgr/endpoint_pair_posix.c
index b9ff969..5542a37 100644
--- a/src/core/lib/iomgr/endpoint_pair_posix.c
+++ b/src/core/lib/iomgr/endpoint_pair_posix.c
@@ -62,22 +62,25 @@
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE);
}
-grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(
- const char *name, grpc_resource_quota *resource_quota,
- size_t read_slice_size) {
+grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
+ grpc_channel_args *args) {
int sv[2];
grpc_endpoint_pair p;
char *final_name;
create_sockets(sv);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
gpr_asprintf(&final_name, "%s:client", name);
- p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), resource_quota,
- read_slice_size, "socketpair-server");
+ p.client = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], final_name), args,
+ "socketpair-server");
gpr_free(final_name);
gpr_asprintf(&final_name, "%s:server", name);
- p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), resource_quota,
- read_slice_size, "socketpair-client");
+ p.server = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[0], final_name), args,
+ "socketpair-client");
gpr_free(final_name);
+
+ grpc_exec_ctx_finish(&exec_ctx);
return p;
}
diff --git a/src/core/lib/iomgr/endpoint_pair_uv.c b/src/core/lib/iomgr/endpoint_pair_uv.c
index ff24894..9718eb0 100644
--- a/src/core/lib/iomgr/endpoint_pair_uv.c
+++ b/src/core/lib/iomgr/endpoint_pair_uv.c
@@ -41,9 +41,8 @@
#include "src/core/lib/iomgr/endpoint_pair.h"
-grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(
- const char *name, grpc_resource_quota *resource_quota,
- size_t read_slice_size) {
+grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
+ grpc_channel_args *args) {
grpc_endpoint_pair endpoint_pair;
// TODO(mlumish): implement this properly under libuv
GPR_ASSERT(false &&
diff --git a/src/core/lib/iomgr/endpoint_pair_windows.c b/src/core/lib/iomgr/endpoint_pair_windows.c
index 93f71b7..25d6264 100644
--- a/src/core/lib/iomgr/endpoint_pair_windows.c
+++ b/src/core/lib/iomgr/endpoint_pair_windows.c
@@ -83,15 +83,18 @@
}
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(
- const char *name, grpc_resource_quota *resource_quota,
- size_t read_slice_size) {
+ const char *name, grpc_channel_args *channel_args) {
SOCKET sv[2];
grpc_endpoint_pair p;
create_sockets(sv);
- p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"),
- resource_quota, "endpoint:server");
- p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"),
- resource_quota, "endpoint:client");
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ p.client = grpc_tcp_create(&exec_ctx,
+ grpc_winsocket_create(sv[1], "endpoint:client"),
+ channel_args, "endpoint:server");
+ p.server = grpc_tcp_create(&exec_ctx,
+ grpc_winsocket_create(sv[0], "endpoint:server"),
+ channel_args, "endpoint:client");
+ grpc_exec_ctx_finish(&exec_ctx);
return p;
}
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c
index 1dbb64e..fbbca6b 100644
--- a/src/core/lib/iomgr/error.c
+++ b/src/core/lib/iomgr/error.c
@@ -212,7 +212,11 @@
GPR_ASSERT(*err);
uint8_t slots = (uint8_t)(size / sizeof(intptr_t));
if ((*err)->arena_size + slots > (*err)->arena_capacity) {
- (*err)->arena_capacity = (uint8_t)(3 * (*err)->arena_capacity / 2);
+ (*err)->arena_capacity =
+ (uint8_t)GPR_MIN(UINT8_MAX - 1, (3 * (*err)->arena_capacity / 2));
+ if ((*err)->arena_size + slots > (*err)->arena_capacity) {
+ return UINT8_MAX;
+ }
*err = gpr_realloc(
*err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t));
}
@@ -223,10 +227,14 @@
static void internal_set_int(grpc_error **err, grpc_error_ints which,
intptr_t value) {
- // GPR_ASSERT((*err)->ints[which] == UINT8_MAX); // TODO, enforce this
uint8_t slot = (*err)->ints[which];
if (slot == UINT8_MAX) {
slot = get_placement(err, sizeof(value));
+ if (slot == UINT8_MAX) {
+ gpr_log(GPR_ERROR, "Error %p is full, dropping int {\"%s\":%" PRIiPTR "}",
+ *err, error_int_name(which), value);
+ return;
+ }
}
(*err)->ints[which] = slot;
(*err)->arena[slot] = value;
@@ -234,10 +242,16 @@
static void internal_set_str(grpc_error **err, grpc_error_strs which,
grpc_slice value) {
- // GPR_ASSERT((*err)->strs[which] == UINT8_MAX); // TODO, enforce this
uint8_t slot = (*err)->strs[which];
if (slot == UINT8_MAX) {
slot = get_placement(err, sizeof(value));
+ if (slot == UINT8_MAX) {
+ const char *str = grpc_slice_to_c_string(value);
+ gpr_log(GPR_ERROR, "Error %p is full, dropping string {\"%s\":\"%s\"}",
+ *err, error_str_name(which), str);
+ gpr_free((void *)str);
+ return;
+ }
} else {
unref_slice(*(grpc_slice *)((*err)->arena + slot));
}
@@ -245,12 +259,19 @@
memcpy((*err)->arena + slot, &value, sizeof(value));
}
+static char *fmt_time(gpr_timespec tm);
static void internal_set_time(grpc_error **err, grpc_error_times which,
gpr_timespec value) {
- // GPR_ASSERT((*err)->times[which] == UINT8_MAX); // TODO, enforce this
uint8_t slot = (*err)->times[which];
if (slot == UINT8_MAX) {
slot = get_placement(err, sizeof(value));
+ if (slot == UINT8_MAX) {
+ const char *time_str = fmt_time(value);
+ gpr_log(GPR_ERROR, "Error %p is full, dropping \"%s\":\"%s\"}", *err,
+ error_time_name(which), time_str);
+ gpr_free((void *)time_str);
+ return;
+ }
}
(*err)->times[which] = slot;
memcpy((*err)->arena + slot, &value, sizeof(value));
@@ -259,6 +280,12 @@
static void internal_add_error(grpc_error **err, grpc_error *new) {
grpc_linked_error new_last = {new, UINT8_MAX};
uint8_t slot = get_placement(err, sizeof(grpc_linked_error));
+ if (slot == UINT8_MAX) {
+ gpr_log(GPR_ERROR, "Error %p is full, dropping error %p = %s", *err, new,
+ grpc_error_string(new));
+ GRPC_ERROR_UNREF(new);
+ return;
+ }
if ((*err)->first_err == UINT8_MAX) {
GPR_ASSERT((*err)->last_err == UINT8_MAX);
(*err)->last_err = slot;
diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c
index b5be550..13409a4 100644
--- a/src/core/lib/iomgr/ev_posix.c
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -111,6 +111,12 @@
}
}
+/* This should be used for testing purposes ONLY */
+void grpc_set_event_engine_test_only(
+ const grpc_event_engine_vtable *ev_engine) {
+ g_event_engine = ev_engine;
+}
+
/* Call this only after calling grpc_event_engine_init() */
const char *grpc_get_poll_strategy_name() { return g_poll_strategy_name; }
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 1a9e5c1..becc4d3 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -183,4 +183,7 @@
typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int);
extern grpc_poll_function_type grpc_poll_function;
+/* This should be used for testing purposes ONLY */
+void grpc_set_event_engine_test_only(const grpc_event_engine_vtable *);
+
#endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */
diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c
index 8dcd80d..c3ee878 100644
--- a/src/core/lib/iomgr/resource_quota.c
+++ b/src/core/lib/iomgr/resource_quota.c
@@ -142,6 +142,8 @@
/* Amount of free memory in the resource quota */
int64_t free_pool;
+ gpr_atm last_size;
+
/* Has rq_step been scheduled to occur? */
bool step_scheduled;
/* Are we currently reclaiming memory */
@@ -581,6 +583,7 @@
resource_quota->combiner = grpc_combiner_create(NULL);
resource_quota->free_pool = INT64_MAX;
resource_quota->size = INT64_MAX;
+ gpr_atm_no_barrier_store(&resource_quota->last_size, GPR_ATM_MAX);
resource_quota->step_scheduled = false;
resource_quota->reclaiming = false;
gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0);
@@ -643,11 +646,17 @@
rq_resize_args *a = gpr_malloc(sizeof(*a));
a->resource_quota = grpc_resource_quota_ref_internal(resource_quota);
a->size = (int64_t)size;
+ gpr_atm_no_barrier_store(&resource_quota->last_size,
+ (gpr_atm)GPR_MIN((size_t)GPR_ATM_MAX, size));
grpc_closure_init(&a->closure, rq_resize, a, grpc_schedule_on_exec_ctx);
grpc_closure_sched(&exec_ctx, &a->closure, GRPC_ERROR_NONE);
grpc_exec_ctx_finish(&exec_ctx);
}
+size_t grpc_resource_quota_peek_size(grpc_resource_quota *resource_quota) {
+ return (size_t)gpr_atm_no_barrier_load(&resource_quota->last_size);
+}
+
/*******************************************************************************
* grpc_resource_user channel args api
*/
diff --git a/src/core/lib/iomgr/resource_quota.h b/src/core/lib/iomgr/resource_quota.h
index b9f62cb..6f99be0 100644
--- a/src/core/lib/iomgr/resource_quota.h
+++ b/src/core/lib/iomgr/resource_quota.h
@@ -90,6 +90,8 @@
double grpc_resource_quota_get_memory_pressure(
grpc_resource_quota *resource_quota);
+size_t grpc_resource_quota_peek_size(grpc_resource_quota *resource_quota);
+
typedef struct grpc_resource_user grpc_resource_user;
grpc_resource_user *grpc_resource_user_create(
diff --git a/src/core/lib/iomgr/tcp_client.h b/src/core/lib/iomgr/tcp_client.h
index 0485661..bc367bd 100644
--- a/src/core/lib/iomgr/tcp_client.h
+++ b/src/core/lib/iomgr/tcp_client.h
@@ -40,10 +40,6 @@
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/resolve_address.h"
-/* Channel arg (integer) setting how large a slice to try and read from the wire
- each time recvmsg (or equivalent) is called */
-#define GRPC_ARG_TCP_READ_CHUNK_SIZE "grpc.experimental.tcp_read_chunk_size"
-
/* Asynchronously connect to an address (specified as (addr, len)), and call
cb with arg and the completed connection when done (or call cb with arg and
NULL on failure).
diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c
index a108b10..a269270 100644
--- a/src/core/lib/iomgr/tcp_client_posix.c
+++ b/src/core/lib/iomgr/tcp_client_posix.c
@@ -137,29 +137,7 @@
grpc_endpoint *grpc_tcp_client_create_from_fd(
grpc_exec_ctx *exec_ctx, grpc_fd *fd, const grpc_channel_args *channel_args,
const char *addr_str) {
- size_t tcp_read_chunk_size = GRPC_TCP_DEFAULT_READ_SLICE_SIZE;
- grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL);
- if (channel_args != NULL) {
- for (size_t i = 0; i < channel_args->num_args; i++) {
- if (0 ==
- strcmp(channel_args->args[i].key, GRPC_ARG_TCP_READ_CHUNK_SIZE)) {
- grpc_integer_options options = {(int)tcp_read_chunk_size, 1,
- 8 * 1024 * 1024};
- tcp_read_chunk_size = (size_t)grpc_channel_arg_get_integer(
- &channel_args->args[i], options);
- } else if (0 ==
- strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
- grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
- resource_quota = grpc_resource_quota_ref_internal(
- channel_args->args[i].value.pointer.p);
- }
- }
- }
-
- grpc_endpoint *ep =
- grpc_tcp_create(fd, resource_quota, tcp_read_chunk_size, addr_str);
- grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
- return ep;
+ return grpc_tcp_create(exec_ctx, fd, channel_args, addr_str);
}
static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
diff --git a/src/core/lib/iomgr/tcp_client_windows.c b/src/core/lib/iomgr/tcp_client_windows.c
index a356564..d6baca5 100644
--- a/src/core/lib/iomgr/tcp_client_windows.c
+++ b/src/core/lib/iomgr/tcp_client_windows.c
@@ -63,7 +63,7 @@
int refs;
grpc_closure on_connect;
grpc_endpoint **endpoint;
- grpc_resource_quota *resource_quota;
+ grpc_channel_args *channel_args;
} async_connect;
static void async_connect_unlock_and_cleanup(grpc_exec_ctx *exec_ctx,
@@ -72,7 +72,7 @@
int done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu);
if (done) {
- grpc_resource_quota_unref_internal(exec_ctx, ac->resource_quota);
+ grpc_channel_args_destroy(exec_ctx, ac->channel_args);
gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_name);
gpr_free(ac);
@@ -119,7 +119,8 @@
if (!wsa_success) {
error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
} else {
- *ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name);
+ *ep =
+ grpc_tcp_create(exec_ctx, socket, ac->channel_args, ac->addr_name);
socket = NULL;
}
} else {
@@ -152,17 +153,6 @@
grpc_winsocket_callback_info *info;
grpc_error *error = GRPC_ERROR_NONE;
- grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL);
- if (channel_args != NULL) {
- for (size_t i = 0; i < channel_args->num_args; i++) {
- if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
- grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
- resource_quota = grpc_resource_quota_ref_internal(
- channel_args->args[i].value.pointer.p);
- }
- }
- }
-
*endpoint = NULL;
/* Use dualstack sockets where available. */
@@ -225,7 +215,7 @@
ac->refs = 2;
ac->addr_name = grpc_sockaddr_to_uri(addr);
ac->endpoint = endpoint;
- ac->resource_quota = resource_quota;
+ ac->channel_args = grpc_channel_args_copy(channel_args);
grpc_closure_init(&ac->on_connect, on_connect, ac, grpc_schedule_on_exec_ctx);
grpc_closure_init(&ac->on_alarm, on_alarm, ac, grpc_schedule_on_exec_ctx);
@@ -247,7 +237,6 @@
} else if (sock != INVALID_SOCKET) {
closesocket(sock);
}
- grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
grpc_closure_sched(exec_ctx, on_done, final_error);
}
diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c
index 4d7cf3f..5f4b38d 100644
--- a/src/core/lib/iomgr/tcp_posix.c
+++ b/src/core/lib/iomgr/tcp_posix.c
@@ -52,7 +52,9 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/profiling/timers.h"
@@ -80,10 +82,14 @@
int fd;
bool finished_edge;
msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */
- size_t slice_size;
+ double target_length;
+ double bytes_read_this_round;
gpr_refcount refcount;
gpr_atm shutdown_count;
+ int min_read_chunk_size;
+ int max_read_chunk_size;
+
/* garbage after the last read */
grpc_slice_buffer last_read_buffer;
@@ -108,6 +114,42 @@
grpc_resource_user_slice_allocator slice_allocator;
} grpc_tcp;
+static void add_to_estimate(grpc_tcp *tcp, size_t bytes) {
+ tcp->bytes_read_this_round += (double)bytes;
+}
+
+static void finish_estimate(grpc_tcp *tcp) {
+ /* If we read >80% of the target buffer in one read loop, increase the size
+ of the target buffer to either the amount read, or twice its previous
+ value */
+ if (tcp->bytes_read_this_round > tcp->target_length * 0.8) {
+ tcp->target_length =
+ GPR_MAX(2 * tcp->target_length, tcp->bytes_read_this_round);
+ } else {
+ tcp->target_length =
+ 0.99 * tcp->target_length + 0.01 * tcp->bytes_read_this_round;
+ }
+ tcp->bytes_read_this_round = 0;
+}
+
+static size_t get_target_read_size(grpc_tcp *tcp) {
+ grpc_resource_quota *rq = grpc_resource_user_quota(tcp->resource_user);
+ double pressure = grpc_resource_quota_get_memory_pressure(rq);
+ double target =
+ tcp->target_length * (pressure > 0.8 ? (1.0 - pressure) / 0.2 : 1.0);
+ size_t sz = (((size_t)GPR_CLAMP(target, tcp->min_read_chunk_size,
+ tcp->max_read_chunk_size)) +
+ 255) &
+ ~(size_t)255;
+ /* don't use more than 1/16th of the overall resource quota for a single read
+ * alloc */
+ size_t rqmax = grpc_resource_quota_peek_size(rq);
+ if (sz > rqmax / 16 && rqmax > 1024) {
+ sz = rqmax / 16;
+ }
+ return sz;
+}
+
static grpc_error *tcp_annotate_error(grpc_error *src_error, grpc_tcp *tcp) {
return grpc_error_set_str(
grpc_error_set_int(src_error, GRPC_ERROR_INT_FD, tcp->fd),
@@ -232,9 +274,7 @@
/* NB: After calling call_read_cb a parallel call of the read handler may
* be running. */
if (errno == EAGAIN) {
- if (tcp->iov_size > 1) {
- tcp->iov_size /= 2;
- }
+ finish_estimate(tcp);
/* We've consumed the edge, request a new one */
grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
} else {
@@ -253,14 +293,13 @@
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Socket closed"), tcp));
TCP_UNREF(exec_ctx, tcp, "read");
} else {
+ add_to_estimate(tcp, (size_t)read_bytes);
GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length);
if ((size_t)read_bytes < tcp->incoming_buffer->length) {
grpc_slice_buffer_trim_end(
tcp->incoming_buffer,
tcp->incoming_buffer->length - (size_t)read_bytes,
&tcp->last_read_buffer);
- } else if (tcp->iov_size < MAX_READ_IOVEC) {
- ++tcp->iov_size;
}
GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length);
call_read_cb(exec_ctx, tcp, GRPC_ERROR_NONE);
@@ -285,11 +324,11 @@
}
static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
- if (tcp->incoming_buffer->count < (size_t)tcp->iov_size) {
- grpc_resource_user_alloc_slices(
- exec_ctx, &tcp->slice_allocator, tcp->slice_size,
- (size_t)tcp->iov_size - tcp->incoming_buffer->count,
- tcp->incoming_buffer);
+ size_t target_read_size = get_target_read_size(tcp);
+ if (tcp->incoming_buffer->length < target_read_size &&
+ tcp->incoming_buffer->count < MAX_READ_IOVEC) {
+ grpc_resource_user_alloc_slices(exec_ctx, &tcp->slice_allocator,
+ target_read_size, 1, tcp->incoming_buffer);
} else {
tcp_do_read(exec_ctx, tcp);
}
@@ -540,9 +579,50 @@
tcp_get_peer,
tcp_get_fd};
-grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd,
- grpc_resource_quota *resource_quota,
- size_t slice_size, const char *peer_string) {
+#define MAX_CHUNK_SIZE 32 * 1024 * 1024
+
+grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_fd *em_fd,
+ const grpc_channel_args *channel_args,
+ const char *peer_string) {
+ int tcp_read_chunk_size = GRPC_TCP_DEFAULT_READ_SLICE_SIZE;
+ int tcp_max_read_chunk_size = 4 * 1024 * 1024;
+ int tcp_min_read_chunk_size = 256;
+ grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL);
+ if (channel_args != NULL) {
+ for (size_t i = 0; i < channel_args->num_args; i++) {
+ if (0 ==
+ strcmp(channel_args->args[i].key, GRPC_ARG_TCP_READ_CHUNK_SIZE)) {
+ grpc_integer_options options = {(int)tcp_read_chunk_size, 1,
+ MAX_CHUNK_SIZE};
+ tcp_read_chunk_size =
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
+ } else if (0 == strcmp(channel_args->args[i].key,
+ GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE)) {
+ grpc_integer_options options = {(int)tcp_read_chunk_size, 1,
+ MAX_CHUNK_SIZE};
+ tcp_min_read_chunk_size =
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
+ } else if (0 == strcmp(channel_args->args[i].key,
+ GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE)) {
+ grpc_integer_options options = {(int)tcp_read_chunk_size, 1,
+ MAX_CHUNK_SIZE};
+ tcp_max_read_chunk_size =
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
+ } else if (0 ==
+ strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
+ resource_quota = grpc_resource_quota_ref_internal(
+ channel_args->args[i].value.pointer.p);
+ }
+ }
+ }
+
+ if (tcp_min_read_chunk_size > tcp_max_read_chunk_size) {
+ tcp_min_read_chunk_size = tcp_max_read_chunk_size;
+ }
+ tcp_read_chunk_size = GPR_CLAMP(tcp_read_chunk_size, tcp_min_read_chunk_size,
+ tcp_max_read_chunk_size);
+
grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
tcp->base.vtable = &vtable;
tcp->peer_string = gpr_strdup(peer_string);
@@ -552,7 +632,10 @@
tcp->release_fd_cb = NULL;
tcp->release_fd = NULL;
tcp->incoming_buffer = NULL;
- tcp->slice_size = slice_size;
+ tcp->target_length = (double)tcp_read_chunk_size;
+ tcp->min_read_chunk_size = tcp_min_read_chunk_size;
+ tcp->max_read_chunk_size = tcp_max_read_chunk_size;
+ tcp->bytes_read_this_round = 0;
tcp->iov_size = 1;
tcp->finished_edge = true;
/* paired with unref in grpc_tcp_destroy */
@@ -569,6 +652,7 @@
&tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp);
/* Tell network status tracker about new endpoint */
grpc_network_status_register_endpoint(&tcp->base);
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
return &tcp->base;
}
diff --git a/src/core/lib/iomgr/tcp_posix.h b/src/core/lib/iomgr/tcp_posix.h
index 1c0d13f..1ad5788 100644
--- a/src/core/lib/iomgr/tcp_posix.h
+++ b/src/core/lib/iomgr/tcp_posix.h
@@ -47,14 +47,13 @@
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/ev_posix.h"
-#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192
-
extern int grpc_tcp_trace;
/* Create a tcp endpoint given a file desciptor and a read slice size.
Takes ownership of fd. */
-grpc_endpoint *grpc_tcp_create(grpc_fd *fd, grpc_resource_quota *resource_quota,
- size_t read_slice_size, const char *peer_string);
+grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
+ const grpc_channel_args *args,
+ const char *peer_string);
/* Return the tcp endpoint's fd, or -1 if this is not available. Does not
release the fd.
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index d6a017c..e66ffc9 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -59,6 +59,7 @@
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@@ -90,7 +91,6 @@
grpc_tcp_server *s = gpr_zalloc(sizeof(grpc_tcp_server));
s->so_reuseport = has_so_reuseport;
- s->resource_quota = grpc_resource_quota_create(NULL);
s->expand_wildcard_addrs = false;
for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
@@ -98,27 +98,14 @@
s->so_reuseport =
has_so_reuseport && (args->args[i].value.integer != 0);
} else {
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
gpr_free(s);
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(GRPC_ARG_ALLOW_REUSEPORT
" must be an integer");
}
- } else if (0 == strcmp(GRPC_ARG_RESOURCE_QUOTA, args->args[i].key)) {
- if (args->args[i].type == GRPC_ARG_POINTER) {
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
- s->resource_quota =
- grpc_resource_quota_ref_internal(args->args[i].value.pointer.p);
- } else {
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
- gpr_free(s);
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- GRPC_ARG_RESOURCE_QUOTA " must be a pointer to a buffer pool");
- }
} else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) {
if (args->args[i].type == GRPC_ARG_INTEGER) {
s->expand_wildcard_addrs = (args->args[i].value.integer != 0);
} else {
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
gpr_free(s);
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
GRPC_ARG_EXPAND_WILDCARD_ADDRS " must be an integer");
@@ -138,6 +125,7 @@
s->head = NULL;
s->tail = NULL;
s->nports = 0;
+ s->channel_args = grpc_channel_args_copy(args);
gpr_atm_no_barrier_store(&s->next_pollset_to_assign, 0);
*server = s;
return GRPC_ERROR_NONE;
@@ -158,8 +146,7 @@
s->head = sp->next;
gpr_free(sp);
}
-
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
+ grpc_channel_args_destroy(exec_ctx, s->channel_args);
gpr_free(s);
}
@@ -286,8 +273,7 @@
sp->server->on_accept_cb(
exec_ctx, sp->server->on_accept_cb_arg,
- grpc_tcp_create(fdobj, sp->server->resource_quota,
- GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str),
+ grpc_tcp_create(exec_ctx, fdobj, sp->server->channel_args, addr_str),
read_notifier_pollset, acceptor);
gpr_free(name);
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h
index f5dc853..c15e2e1 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix.h
+++ b/src/core/lib/iomgr/tcp_server_utils_posix.h
@@ -103,7 +103,8 @@
/* next pollset to assign a channel to */
gpr_atm next_pollset_to_assign;
- grpc_resource_quota *resource_quota;
+ /* channel args for this server */
+ grpc_channel_args *channel_args;
};
/* If successful, add a listener to \a s for \a addr, set \a dsmode for the
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index 12ce7d3..4c17f08 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -46,6 +46,7 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/pollset_windows.h"
#include "src/core/lib/iomgr/resolve_address.h"
@@ -102,7 +103,7 @@
/* shutdown callback */
grpc_closure *shutdown_complete;
- grpc_resource_quota *resource_quota;
+ grpc_channel_args *channel_args;
};
/* Public function. Allocates the proper data structures to hold a
@@ -112,21 +113,7 @@
const grpc_channel_args *args,
grpc_tcp_server **server) {
grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
- s->resource_quota = grpc_resource_quota_create(NULL);
- for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
- if (0 == strcmp(GRPC_ARG_RESOURCE_QUOTA, args->args[i].key)) {
- if (args->args[i].type == GRPC_ARG_POINTER) {
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
- s->resource_quota =
- grpc_resource_quota_ref_internal(args->args[i].value.pointer.p);
- } else {
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
- gpr_free(s);
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- GRPC_ARG_RESOURCE_QUOTA " must be a pointer to a buffer pool");
- }
- }
- }
+ s->channel_args = grpc_channel_args_copy(args);
gpr_ref_init(&s->refs, 1);
gpr_mu_init(&s->mu);
s->active_ports = 0;
@@ -155,7 +142,7 @@
grpc_winsocket_destroy(sp->socket);
gpr_free(sp);
}
- grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
+ grpc_channel_args_destroy(exec_ctx, s->channel_args);
gpr_free(s);
}
@@ -383,8 +370,8 @@
gpr_free(utf8_message);
}
gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
- ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name),
- sp->server->resource_quota, peer_name_string);
+ ep = grpc_tcp_create(exec_ctx, grpc_winsocket_create(sock, fd_name),
+ sp->server->channel_args, peer_name_string);
gpr_free(fd_name);
gpr_free(peer_name_string);
} else {
diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c
index 9134883..f74aa68 100644
--- a/src/core/lib/iomgr/tcp_windows.c
+++ b/src/core/lib/iomgr/tcp_windows.c
@@ -430,9 +430,19 @@
win_get_peer,
win_get_fd};
-grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket,
- grpc_resource_quota *resource_quota,
+grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
+ grpc_channel_args *channel_args,
char *peer_string) {
+ grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL);
+ if (channel_args != NULL) {
+ for (size_t i = 0; i < channel_args->num_args; i++) {
+ if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
+ resource_quota = grpc_resource_quota_ref_internal(
+ channel_args->args[i].value.pointer.p);
+ }
+ }
+ }
grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
memset(tcp, 0, sizeof(grpc_tcp));
tcp->base.vtable = &vtable;
diff --git a/src/core/lib/iomgr/tcp_windows.h b/src/core/lib/iomgr/tcp_windows.h
index 4402de1..abafdb2 100644
--- a/src/core/lib/iomgr/tcp_windows.h
+++ b/src/core/lib/iomgr/tcp_windows.h
@@ -50,8 +50,8 @@
/* Create a tcp endpoint given a winsock handle.
* Takes ownership of the handle.
*/
-grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket,
- grpc_resource_quota *resource_quota,
+grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
+ grpc_channel_args *channel_args,
char *peer_string);
grpc_error *grpc_tcp_prepare_socket(SOCKET sock);
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 2b51706..dbe3263 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -448,14 +448,14 @@
typedef struct {
grpc_channel_security_connector base;
- tsi_ssl_handshaker_factory *handshaker_factory;
+ tsi_ssl_client_handshaker_factory *handshaker_factory;
char *target_name;
char *overridden_target_name;
} grpc_ssl_channel_security_connector;
typedef struct {
grpc_server_security_connector base;
- tsi_ssl_handshaker_factory *handshaker_factory;
+ tsi_ssl_server_handshaker_factory *handshaker_factory;
} grpc_ssl_server_security_connector;
static void ssl_channel_destroy(grpc_exec_ctx *exec_ctx,
@@ -464,7 +464,7 @@
(grpc_ssl_channel_security_connector *)sc;
grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds);
if (c->handshaker_factory != NULL) {
- tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
+ tsi_ssl_client_handshaker_factory_destroy(c->handshaker_factory);
}
if (c->target_name != NULL) gpr_free(c->target_name);
if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
@@ -476,26 +476,11 @@
grpc_ssl_server_security_connector *c =
(grpc_ssl_server_security_connector *)sc;
if (c->handshaker_factory != NULL) {
- tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
+ tsi_ssl_server_handshaker_factory_destroy(c->handshaker_factory);
}
gpr_free(sc);
}
-static grpc_security_status ssl_create_handshaker(
- tsi_ssl_handshaker_factory *handshaker_factory, bool is_client,
- const char *peer_name, tsi_handshaker **handshaker) {
- tsi_result result = TSI_OK;
- if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR;
- result = tsi_ssl_handshaker_factory_create_handshaker(
- handshaker_factory, is_client ? peer_name : NULL, handshaker);
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
- tsi_result_to_string(result));
- return GRPC_SECURITY_ERROR;
- }
- return GRPC_SECURITY_OK;
-}
-
static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
grpc_handshake_manager *handshake_mgr) {
@@ -503,11 +488,17 @@
(grpc_ssl_channel_security_connector *)sc;
// Instantiate TSI handshaker.
tsi_handshaker *tsi_hs = NULL;
- ssl_create_handshaker(c->handshaker_factory, true /* is_client */,
- c->overridden_target_name != NULL
- ? c->overridden_target_name
- : c->target_name,
- &tsi_hs);
+ tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
+ c->handshaker_factory,
+ c->overridden_target_name != NULL ? c->overridden_target_name
+ : c->target_name,
+ &tsi_hs);
+ if (result != TSI_OK) {
+ gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
+ tsi_result_to_string(result));
+ return;
+ }
+
// Create handshakers.
grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
exec_ctx, tsi_hs, &sc->base));
@@ -520,8 +511,14 @@
(grpc_ssl_server_security_connector *)sc;
// Instantiate TSI handshaker.
tsi_handshaker *tsi_hs = NULL;
- ssl_create_handshaker(c->handshaker_factory, false /* is_client */,
- NULL /* peer_name */, &tsi_hs);
+ tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
+ c->handshaker_factory, &tsi_hs);
+ if (result != TSI_OK) {
+ gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
+ tsi_result_to_string(result));
+ return;
+ }
+
// Create handshakers.
grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
exec_ctx, tsi_hs, &sc->base));
diff --git a/src/core/lib/slice/slice_buffer.c b/src/core/lib/slice/slice_buffer.c
index 9176dc8..c96b9c3 100644
--- a/src/core/lib/slice/slice_buffer.c
+++ b/src/core/lib/slice/slice_buffer.c
@@ -46,27 +46,29 @@
#define GROW(x) (3 * (x) / 2)
static void maybe_embiggen(grpc_slice_buffer *sb) {
- if (sb->base_slices != sb->slices) {
- memmove(sb->base_slices, sb->slices, sb->count * sizeof(grpc_slice));
- sb->slices = sb->base_slices;
- }
-
/* How far away from sb->base_slices is sb->slices pointer */
size_t slice_offset = (size_t)(sb->slices - sb->base_slices);
size_t slice_count = sb->count + slice_offset;
if (slice_count == sb->capacity) {
- sb->capacity = GROW(sb->capacity);
- GPR_ASSERT(sb->capacity > slice_count);
- if (sb->base_slices == sb->inlined) {
- sb->base_slices = gpr_malloc(sb->capacity * sizeof(grpc_slice));
- memcpy(sb->base_slices, sb->inlined, slice_count * sizeof(grpc_slice));
+ if (sb->base_slices != sb->slices) {
+ /* Make room by moving elements if there's still space unused */
+ memmove(sb->base_slices, sb->slices, sb->count * sizeof(grpc_slice));
+ sb->slices = sb->base_slices;
} else {
- sb->base_slices =
- gpr_realloc(sb->base_slices, sb->capacity * sizeof(grpc_slice));
- }
+ /* Allocate more memory if no more space is available */
+ sb->capacity = GROW(sb->capacity);
+ GPR_ASSERT(sb->capacity > slice_count);
+ if (sb->base_slices == sb->inlined) {
+ sb->base_slices = gpr_malloc(sb->capacity * sizeof(grpc_slice));
+ memcpy(sb->base_slices, sb->inlined, slice_count * sizeof(grpc_slice));
+ } else {
+ sb->base_slices =
+ gpr_realloc(sb->base_slices, sb->capacity * sizeof(grpc_slice));
+ }
- sb->slices = sb->base_slices + slice_offset;
+ sb->slices = sb->base_slices + slice_offset;
+ }
}
}
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index c37ead2..97d50a9 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -145,16 +145,28 @@
grpc_transport_stream_op_batch op;
} batch_control;
+typedef struct {
+ gpr_mu child_list_mu;
+ grpc_call *first_child;
+} parent_call;
+
+typedef struct {
+ grpc_call *parent;
+ /** siblings: children of the same parent form a list, and this list is
+ protected under
+ parent->mu */
+ grpc_call *sibling_next;
+ grpc_call *sibling_prev;
+} child_call;
+
struct grpc_call {
gpr_arena *arena;
grpc_completion_queue *cq;
grpc_polling_entity pollent;
grpc_channel *channel;
- grpc_call *parent;
- grpc_call *first_child;
gpr_timespec start_time;
- /* protects first_child, and child next/prev links */
- gpr_mu child_list_mu;
+ /* parent_call* */ gpr_atm parent_call_atm;
+ child_call *child_call;
/* client or server call */
bool is_client;
@@ -206,12 +218,6 @@
int send_extra_metadata_count;
gpr_timespec send_deadline;
- /** siblings: children of the same parent form a list, and this list is
- protected under
- parent->mu */
- grpc_call *sibling_next;
- grpc_call *sibling_prev;
-
grpc_slice_buffer_stream sending_stream;
grpc_byte_stream *receiving_stream;
@@ -276,6 +282,23 @@
*composite = grpc_error_add_child(*composite, new);
}
+static parent_call *get_or_create_parent_call(grpc_call *call) {
+ parent_call *p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
+ if (p == NULL) {
+ p = gpr_arena_alloc(call->arena, sizeof(*p));
+ gpr_mu_init(&p->child_list_mu);
+ if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm)NULL, (gpr_atm)p)) {
+ gpr_mu_destroy(&p->child_list_mu);
+ p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
+ }
+ }
+ return p;
+}
+
+static parent_call *get_parent_call(grpc_call *call) {
+ return (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
+}
+
grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
const grpc_call_create_args *args,
grpc_call **out_call) {
@@ -291,10 +314,8 @@
sizeof(grpc_call) + channel_stack->call_stack_size);
call->arena = arena;
*out_call = call;
- gpr_mu_init(&call->child_list_mu);
call->channel = args->channel;
call->cq = args->cq;
- call->parent = args->parent_call;
call->start_time = gpr_now(GPR_CLOCK_MONOTONIC);
/* Always support no compression */
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
@@ -326,11 +347,17 @@
gpr_convert_clock_type(args->send_deadline, GPR_CLOCK_MONOTONIC);
if (args->parent_call != NULL) {
+ child_call *cc = call->child_call =
+ gpr_arena_alloc(arena, sizeof(child_call));
+ call->child_call->parent = args->parent_call;
+
GRPC_CALL_INTERNAL_REF(args->parent_call, "child");
GPR_ASSERT(call->is_client);
GPR_ASSERT(!args->parent_call->is_client);
- gpr_mu_lock(&args->parent_call->child_list_mu);
+ parent_call *pc = get_or_create_parent_call(args->parent_call);
+
+ gpr_mu_lock(&pc->child_list_mu);
if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) {
send_deadline = gpr_time_min(
@@ -364,17 +391,17 @@
}
}
- if (args->parent_call->first_child == NULL) {
- args->parent_call->first_child = call;
- call->sibling_next = call->sibling_prev = call;
+ if (pc->first_child == NULL) {
+ pc->first_child = call;
+ cc->sibling_next = cc->sibling_prev = call;
} else {
- call->sibling_next = args->parent_call->first_child;
- call->sibling_prev = args->parent_call->first_child->sibling_prev;
- call->sibling_next->sibling_prev = call->sibling_prev->sibling_next =
- call;
+ cc->sibling_next = pc->first_child;
+ cc->sibling_prev = pc->first_child->child_call->sibling_prev;
+ cc->sibling_next->child_call->sibling_prev =
+ cc->sibling_prev->child_call->sibling_next = call;
}
- gpr_mu_unlock(&args->parent_call->child_list_mu);
+ gpr_mu_unlock(&pc->child_list_mu);
}
call->send_deadline = send_deadline;
@@ -469,7 +496,10 @@
if (c->receiving_stream != NULL) {
grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
}
- gpr_mu_destroy(&c->child_list_mu);
+ parent_call *pc = get_parent_call(c);
+ if (pc != NULL) {
+ gpr_mu_destroy(&pc->child_list_mu);
+ }
for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md);
}
@@ -499,31 +529,31 @@
}
void grpc_call_destroy(grpc_call *c) {
- int cancel;
- grpc_call *parent = c->parent;
+ child_call *cc = c->child_call;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_TIMER_BEGIN("grpc_call_destroy", 0);
GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
- if (parent) {
- gpr_mu_lock(&parent->child_list_mu);
- if (c == parent->first_child) {
- parent->first_child = c->sibling_next;
- if (c == parent->first_child) {
- parent->first_child = NULL;
+ if (cc) {
+ parent_call *pc = get_parent_call(cc->parent);
+ gpr_mu_lock(&pc->child_list_mu);
+ if (c == pc->first_child) {
+ pc->first_child = cc->sibling_next;
+ if (c == pc->first_child) {
+ pc->first_child = NULL;
}
}
- c->sibling_prev->sibling_next = c->sibling_next;
- c->sibling_next->sibling_prev = c->sibling_prev;
- gpr_mu_unlock(&parent->child_list_mu);
- GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
+ cc->sibling_prev->child_call->sibling_next = cc->sibling_next;
+ cc->sibling_next->child_call->sibling_prev = cc->sibling_prev;
+ gpr_mu_unlock(&pc->child_list_mu);
+ GRPC_CALL_INTERNAL_UNREF(&exec_ctx, cc->parent, "child");
}
GPR_ASSERT(!c->destroy_called);
c->destroy_called = 1;
- cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) &&
- !gpr_atm_acq_load(&c->received_final_op_atm);
+ bool cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) != 0 &&
+ gpr_atm_acq_load(&c->received_final_op_atm) == 0;
if (cancel) {
cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
GRPC_ERROR_CANCELLED);
@@ -1079,7 +1109,6 @@
static void post_batch_completion(grpc_exec_ctx *exec_ctx,
batch_control *bctl) {
- grpc_call *child_call;
grpc_call *next_child_call;
grpc_call *call = bctl->call;
grpc_error *error = consolidate_batch_errors(bctl);
@@ -1104,21 +1133,25 @@
/* propagate cancellation to any interested children */
gpr_atm_rel_store(&call->received_final_op_atm, 1);
- gpr_mu_lock(&call->child_list_mu);
- child_call = call->first_child;
- if (child_call != NULL) {
- do {
- next_child_call = child_call->sibling_next;
- if (child_call->cancellation_is_inherited) {
- GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
- cancel_with_error(exec_ctx, child_call, STATUS_FROM_API_OVERRIDE,
- GRPC_ERROR_CANCELLED);
- GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
- }
- child_call = next_child_call;
- } while (child_call != call->first_child);
+ parent_call *pc = get_parent_call(call);
+ if (pc != NULL) {
+ grpc_call *child;
+ gpr_mu_lock(&pc->child_list_mu);
+ child = pc->first_child;
+ if (child != NULL) {
+ do {
+ next_child_call = child->child_call->sibling_next;
+ if (child->cancellation_is_inherited) {
+ GRPC_CALL_INTERNAL_REF(child, "propagate_cancel");
+ cancel_with_error(exec_ctx, child, STATUS_FROM_API_OVERRIDE,
+ GRPC_ERROR_CANCELLED);
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, child, "propagate_cancel");
+ }
+ child = next_child_call;
+ } while (child != pc->first_child);
+ }
+ gpr_mu_unlock(&pc->child_list_mu);
}
- gpr_mu_unlock(&call->child_list_mu);
if (call->is_client) {
get_final_status(call, set_status_value_directly,
diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c
index a0325cc..984f745 100644
--- a/src/core/tsi/ssl_transport_security.c
+++ b/src/core/tsi/ssl_transport_security.c
@@ -81,23 +81,13 @@
/* --- Structure definitions. ---*/
-struct tsi_ssl_handshaker_factory {
- tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory *self,
- const char *server_name_indication,
- tsi_handshaker **handshaker);
- void (*destroy)(tsi_ssl_handshaker_factory *self);
-};
-
-typedef struct {
- tsi_ssl_handshaker_factory base;
+struct tsi_ssl_client_handshaker_factory {
SSL_CTX *ssl_context;
unsigned char *alpn_protocol_list;
size_t alpn_protocol_list_length;
-} tsi_ssl_client_handshaker_factory;
+};
-typedef struct {
- tsi_ssl_handshaker_factory base;
-
+struct tsi_ssl_server_handshaker_factory {
/* Several contexts to support SNI.
The tsi_peer array contains the subject names of the server certificates
associated with the contexts at the same index. */
@@ -106,7 +96,7 @@
size_t ssl_context_count;
unsigned char *alpn_protocol_list;
size_t alpn_protocol_list_length;
-} tsi_ssl_server_handshaker_factory;
+};
typedef struct {
tsi_handshaker base;
@@ -1053,18 +1043,6 @@
/* --- tsi_ssl_handshaker_factory common methods. --- */
-tsi_result tsi_ssl_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory *self, const char *server_name_indication,
- tsi_handshaker **handshaker) {
- if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
- return self->create_handshaker(self, server_name_indication, handshaker);
-}
-
-void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
- if (self == NULL) return;
- self->destroy(self);
-}
-
static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
const char *server_name_indication,
tsi_handshaker **handshaker) {
@@ -1152,24 +1130,20 @@
return SSL_TLSEXT_ERR_NOACK;
}
-/* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
+/* --- tsi_ssl_client_handshaker_factory methods implementation. --- */
-static tsi_result ssl_client_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory *self, const char *server_name_indication,
+tsi_result tsi_ssl_client_handshaker_factory_create_handshaker(
+ tsi_ssl_client_handshaker_factory *self, const char *server_name_indication,
tsi_handshaker **handshaker) {
- tsi_ssl_client_handshaker_factory *impl =
- (tsi_ssl_client_handshaker_factory *)self;
- return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
+ return create_tsi_ssl_handshaker(self->ssl_context, 1, server_name_indication,
handshaker);
}
-static void ssl_client_handshaker_factory_destroy(
- tsi_ssl_handshaker_factory *self) {
- tsi_ssl_client_handshaker_factory *impl =
- (tsi_ssl_client_handshaker_factory *)self;
- if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
- if (impl->alpn_protocol_list != NULL) gpr_free(impl->alpn_protocol_list);
- gpr_free(impl);
+void tsi_ssl_client_handshaker_factory_destroy(
+ tsi_ssl_client_handshaker_factory *self) {
+ if (self->ssl_context != NULL) SSL_CTX_free(self->ssl_context);
+ if (self->alpn_protocol_list != NULL) gpr_free(self->alpn_protocol_list);
+ gpr_free(self);
}
static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
@@ -1186,36 +1160,29 @@
/* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
-static tsi_result ssl_server_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory *self, const char *server_name_indication,
- tsi_handshaker **handshaker) {
- tsi_ssl_server_handshaker_factory *impl =
- (tsi_ssl_server_handshaker_factory *)self;
- if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
- return TSI_INVALID_ARGUMENT;
- }
+tsi_result tsi_ssl_server_handshaker_factory_create_handshaker(
+ tsi_ssl_server_handshaker_factory *self, tsi_handshaker **handshaker) {
+ if (self->ssl_context_count == 0) return TSI_INVALID_ARGUMENT;
/* Create the handshaker with the first context. We will switch if needed
because of SNI in ssl_server_handshaker_factory_servername_callback. */
- return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
+ return create_tsi_ssl_handshaker(self->ssl_contexts[0], 0, NULL, handshaker);
}
-static void ssl_server_handshaker_factory_destroy(
- tsi_ssl_handshaker_factory *self) {
- tsi_ssl_server_handshaker_factory *impl =
- (tsi_ssl_server_handshaker_factory *)self;
+void tsi_ssl_server_handshaker_factory_destroy(
+ tsi_ssl_server_handshaker_factory *self) {
size_t i;
- for (i = 0; i < impl->ssl_context_count; i++) {
- if (impl->ssl_contexts[i] != NULL) {
- SSL_CTX_free(impl->ssl_contexts[i]);
- tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
+ for (i = 0; i < self->ssl_context_count; i++) {
+ if (self->ssl_contexts[i] != NULL) {
+ SSL_CTX_free(self->ssl_contexts[i]);
+ tsi_peer_destruct(&self->ssl_context_x509_subject_names[i]);
}
}
- if (impl->ssl_contexts != NULL) gpr_free(impl->ssl_contexts);
- if (impl->ssl_context_x509_subject_names != NULL) {
- gpr_free(impl->ssl_context_x509_subject_names);
+ if (self->ssl_contexts != NULL) gpr_free(self->ssl_contexts);
+ if (self->ssl_context_x509_subject_names != NULL) {
+ gpr_free(self->ssl_context_x509_subject_names);
}
- if (impl->alpn_protocol_list != NULL) gpr_free(impl->alpn_protocol_list);
- gpr_free(impl);
+ if (self->alpn_protocol_list != NULL) gpr_free(self->alpn_protocol_list);
+ gpr_free(self);
}
static int does_entry_match_name(const char *entry, size_t entry_length,
@@ -1317,7 +1284,7 @@
const unsigned char *pem_root_certs, size_t pem_root_certs_size,
const char *cipher_list, const unsigned char **alpn_protocols,
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory **factory) {
+ tsi_ssl_client_handshaker_factory **factory) {
SSL_CTX *ssl_context = NULL;
tsi_ssl_client_handshaker_factory *impl = NULL;
tsi_result result = TSI_OK;
@@ -1373,16 +1340,13 @@
}
} while (0);
if (result != TSI_OK) {
- ssl_client_handshaker_factory_destroy(&impl->base);
+ tsi_ssl_client_handshaker_factory_destroy(impl);
return result;
}
SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
/* TODO(jboeuf): Add revocation verification. */
- impl->base.create_handshaker =
- ssl_client_handshaker_factory_create_handshaker;
- impl->base.destroy = ssl_client_handshaker_factory_destroy;
- *factory = &impl->base;
+ *factory = impl;
return TSI_OK;
}
@@ -1394,7 +1358,7 @@
size_t pem_client_root_certs_size, int force_client_auth,
const char *cipher_list, const unsigned char **alpn_protocols,
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory **factory) {
+ tsi_ssl_server_handshaker_factory **factory) {
return tsi_create_ssl_server_handshaker_factory_ex(
pem_private_keys, pem_private_keys_sizes, pem_cert_chains,
pem_cert_chains_sizes, key_cert_pair_count, pem_client_root_certs,
@@ -1414,7 +1378,7 @@
tsi_client_certificate_request_type client_certificate_request,
const char *cipher_list, const unsigned char **alpn_protocols,
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory **factory) {
+ tsi_ssl_server_handshaker_factory **factory) {
tsi_ssl_server_handshaker_factory *impl = NULL;
tsi_result result = TSI_OK;
size_t i = 0;
@@ -1429,15 +1393,12 @@
}
impl = gpr_zalloc(sizeof(*impl));
- impl->base.create_handshaker =
- ssl_server_handshaker_factory_create_handshaker;
- impl->base.destroy = ssl_server_handshaker_factory_destroy;
impl->ssl_contexts = gpr_zalloc(key_cert_pair_count * sizeof(SSL_CTX *));
impl->ssl_context_x509_subject_names =
gpr_zalloc(key_cert_pair_count * sizeof(tsi_peer));
if (impl->ssl_contexts == NULL ||
impl->ssl_context_x509_subject_names == NULL) {
- tsi_ssl_handshaker_factory_destroy(&impl->base);
+ tsi_ssl_server_handshaker_factory_destroy(impl);
return TSI_OUT_OF_RESOURCES;
}
impl->ssl_context_count = key_cert_pair_count;
@@ -1447,7 +1408,7 @@
alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
&impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
if (result != TSI_OK) {
- tsi_ssl_handshaker_factory_destroy(&impl->base);
+ tsi_ssl_server_handshaker_factory_destroy(impl);
return result;
}
}
@@ -1520,11 +1481,11 @@
} while (0);
if (result != TSI_OK) {
- tsi_ssl_handshaker_factory_destroy(&impl->base);
+ tsi_ssl_server_handshaker_factory_destroy(impl);
return result;
}
}
- *factory = &impl->base;
+ *factory = impl;
return TSI_OK;
}
diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h
index 0a527e9..48dcaec 100644
--- a/src/core/tsi/ssl_transport_security.h
+++ b/src/core/tsi/ssl_transport_security.h
@@ -52,12 +52,13 @@
#define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
-/* --- tsi_ssl_handshaker_factory object ---
+/* --- tsi_ssl_client_handshaker_factory object ---
- This object creates tsi_handshaker objects implemented in terms of the
- TLS 1.2 specificiation. */
+ This object creates a client tsi_handshaker objects implemented in terms of
+ the TLS 1.2 specificiation. */
-typedef struct tsi_ssl_handshaker_factory tsi_ssl_handshaker_factory;
+typedef struct tsi_ssl_client_handshaker_factory
+ tsi_ssl_client_handshaker_factory;
/* Creates a client handshaker factory.
- pem_private_key is the buffer containing the PEM encoding of the client's
@@ -92,7 +93,33 @@
const unsigned char *pem_root_certs, size_t pem_root_certs_size,
const char *cipher_suites, const unsigned char **alpn_protocols,
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory **factory);
+ tsi_ssl_client_handshaker_factory **factory);
+
+/* Creates a client handshaker.
+ - self is the factory from which the handshaker will be created.
+ - server_name_indication indicates the name of the server the client is
+ trying to connect to which will be relayed to the server using the SNI
+ extension.
+ - handshaker is the address of the handshaker pointer to be created.
+
+ - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
+ where a parameter is invalid. */
+tsi_result tsi_ssl_client_handshaker_factory_create_handshaker(
+ tsi_ssl_client_handshaker_factory *self, const char *server_name_indication,
+ tsi_handshaker **handshaker);
+
+/* Destroys the handshaker factory. WARNING: it is unsafe to destroy a factory
+ while handshakers created with this factory are still in use. */
+void tsi_ssl_client_handshaker_factory_destroy(
+ tsi_ssl_client_handshaker_factory *self);
+
+/* --- tsi_ssl_server_handshaker_factory object ---
+
+ This object creates a client tsi_handshaker objects implemented in terms of
+ the TLS 1.2 specificiation. */
+
+typedef struct tsi_ssl_server_handshaker_factory
+ tsi_ssl_server_handshaker_factory;
/* Creates a server handshaker factory.
- version indicates which version of the specification to use.
@@ -140,7 +167,7 @@
size_t pem_client_root_certs_size, int force_client_auth,
const char *cipher_suites, const unsigned char **alpn_protocols,
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory **factory);
+ tsi_ssl_server_handshaker_factory **factory);
/* Same as tsi_create_ssl_server_handshaker_factory method except uses
tsi_client_certificate_request_type to support more ways to handle client
@@ -157,25 +184,21 @@
tsi_client_certificate_request_type client_certificate_request,
const char *cipher_suites, const unsigned char **alpn_protocols,
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory **factory);
+ tsi_ssl_server_handshaker_factory **factory);
-/* Creates a handshaker.
+/* Creates a server handshaker.
- self is the factory from which the handshaker will be created.
- - server_name_indication indicates the name of the server the client is
- trying to connect to which will be relayed to the server using the SNI
- extension.
- This parameter must be NULL for a server handshaker factory.
- - handhshaker is the address of the handshaker pointer to be created.
+ - handshaker is the address of the handshaker pointer to be created.
- This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
where a parameter is invalid. */
-tsi_result tsi_ssl_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory *self, const char *server_name_indication,
- tsi_handshaker **handshaker);
+tsi_result tsi_ssl_server_handshaker_factory_create_handshaker(
+ tsi_ssl_server_handshaker_factory *self, tsi_handshaker **handshaker);
/* Destroys the handshaker factory. WARNING: it is unsafe to destroy a factory
while handshakers created with this factory are still in use. */
-void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self);
+void tsi_ssl_server_handshaker_factory_destroy(
+ tsi_ssl_server_handshaker_factory *self);
/* Util that checks that an ssl peer matches a specific name.
Still TODO(jboeuf):
diff --git a/src/node/performance/benchmark_client_express.js b/src/node/performance/benchmark_client_express.js
index 675eb5f..e749956 100644
--- a/src/node/performance/benchmark_client_express.js
+++ b/src/node/performance/benchmark_client_express.js
@@ -93,7 +93,7 @@
for (var i = 0; i < channels; i++) {
var host_port;
- host_port = server_targets[i % server_targets.length].split(':')
+ host_port = server_targets[i % server_targets.length].split(':');
var new_options = _.assign({hostname: host_port[0], port: +host_port[1]}, options);
new_options.agent = new protocol.Agent(new_options);
this.client_options[i] = new_options;
@@ -149,6 +149,17 @@
if (self.running) {
self.pending_calls++;
var start_time = process.hrtime();
+ function finishCall(success) {
+ if (success) {
+ var time_diff = process.hrtime(start_time);
+ self.histogram.add(timeDiffToNanos(time_diff));
+ }
+ makeCall(client_options);
+ self.pending_calls--;
+ if ((!self.running) && self.pending_calls == 0) {
+ self.emit('finished');
+ }
+ }
var req = self.request(client_options, function(res) {
var res_data = '';
res.on('data', function(data) {
@@ -156,18 +167,16 @@
});
res.on('end', function() {
JSON.parse(res_data);
- var time_diff = process.hrtime(start_time);
- self.histogram.add(timeDiffToNanos(time_diff));
- makeCall(client_options);
- self.pending_calls--;
- if ((!self.running) && self.pending_calls == 0) {
- self.emit('finished');
- }
+ finishCall(true);
});
});
req.write(JSON.stringify(argument));
req.end();
req.on('error', function(error) {
+ if (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT') {
+ finishCall(false);
+ return;
+ }
self.emit('error', new Error('Client error: ' + error.message));
self.running = false;
});
diff --git a/src/node/performance/benchmark_server_express.js b/src/node/performance/benchmark_server_express.js
index 065bcf6..4b695eb 100644
--- a/src/node/performance/benchmark_server_express.js
+++ b/src/node/performance/benchmark_server_express.js
@@ -46,7 +46,7 @@
var util = require('util');
var express = require('express');
-var bodyParser = require('body-parser')
+var bodyParser = require('body-parser');
function unaryCall(req, res) {
var reqObj = req.body;
@@ -56,7 +56,7 @@
function BenchmarkServer(host, port, tls, generic, response_size) {
var app = express();
- app.use(bodyParser.json())
+ app.use(bodyParser.json());
app.put('/serviceProto.BenchmarkService.service/unaryCall', unaryCall);
this.input_host = host;
this.input_port = port;
diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD
index 23a16a7..6f3422e 100644
--- a/src/proto/grpc/testing/BUILD
+++ b/src/proto/grpc/testing/BUILD
@@ -83,7 +83,11 @@
grpc_proto_library(
name = "services_proto",
srcs = ["services.proto"],
- deps = ["control_proto", "messages_proto"],
+ deps = [
+ "control_proto",
+ "messages_proto",
+ "stats_proto",
+ ],
)
grpc_proto_library(
diff --git a/src/proto/grpc/testing/echo_messages.proto b/src/proto/grpc/testing/echo_messages.proto
index efb6f4d..b82e80d 100644
--- a/src/proto/grpc/testing/echo_messages.proto
+++ b/src/proto/grpc/testing/echo_messages.proto
@@ -38,6 +38,13 @@
string detail = 2;
}
+// Error status client expects to see.
+message ErrorStatus {
+ int32 code = 1;
+ string error_message = 2;
+ string binary_error_details = 3;
+}
+
message RequestParams {
bool echo_deadline = 1;
int32 client_cancel_after_us = 2;
@@ -51,6 +58,8 @@
string expected_transport_security_type = 10;
DebugInfo debug_info = 11;
bool server_die = 12; // Server should not see a request with this set.
+ string binary_error_details = 13;
+ ErrorStatus expected_error = 14;
}
message EchoRequest {
diff --git a/src/proto/grpc/testing/services.proto b/src/proto/grpc/testing/services.proto
index f71dae3..969782d 100644
--- a/src/proto/grpc/testing/services.proto
+++ b/src/proto/grpc/testing/services.proto
@@ -33,6 +33,7 @@
import "src/proto/grpc/testing/messages.proto";
import "src/proto/grpc/testing/control.proto";
+import "src/proto/grpc/testing/stats.proto";
package grpc.testing;
@@ -69,3 +70,8 @@
// Quit this worker
rpc QuitWorker(Void) returns (Void);
}
+
+service ReportQpsScenarioService {
+ // Report results of a QPS test benchmark scenario.
+ rpc ReportScenario(ScenarioResult) returns (Void);
+}
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index 47838c2..f29c44a 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -705,6 +705,10 @@
state.rpc_states.remove(rpc_state)
if _stop_serving(state):
return
+ # We want to force the deletion of the previous event
+ # ~before~ we poll again; if the event has a reference
+ # to a shutdown Call object, this can induce spinlock.
+ event = None
def _stop(state, grace):
diff --git a/src/ruby/end2end/channel_closing_driver.rb b/src/ruby/end2end/channel_closing_driver.rb
index 43e2fe8..d3e5373 100755
--- a/src/ruby/end2end/channel_closing_driver.rb
+++ b/src/ruby/end2end/channel_closing_driver.rb
@@ -36,7 +36,7 @@
def main
STDERR.puts 'start server'
- server_runner = ServerRunner.new
+ server_runner = ServerRunner.new(EchoServerImpl)
server_port = server_runner.run
sleep 1
diff --git a/src/ruby/end2end/channel_state_driver.rb b/src/ruby/end2end/channel_state_driver.rb
index c3184bf..80fb628 100755
--- a/src/ruby/end2end/channel_state_driver.rb
+++ b/src/ruby/end2end/channel_state_driver.rb
@@ -35,7 +35,7 @@
def main
STDERR.puts 'start server'
- server_runner = ServerRunner.new
+ server_runner = ServerRunner.new(EchoServerImpl)
server_port = server_runner.run
sleep 1
diff --git a/src/ruby/end2end/end2end_common.rb b/src/ruby/end2end/end2end_common.rb
index 9534bb2..1c87ced 100755
--- a/src/ruby/end2end/end2end_common.rb
+++ b/src/ruby/end2end/end2end_common.rb
@@ -55,13 +55,14 @@
# ServerRunner starts an "echo server" that test clients can make calls to
class ServerRunner
- def initialize
+ def initialize(service_impl)
+ @service_impl = service_impl
end
def run
@srv = GRPC::RpcServer.new
port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
- @srv.handle(EchoServerImpl)
+ @srv.handle(@service_impl)
@thd = Thread.new do
@srv.run
diff --git a/src/ruby/end2end/killed_client_thread_client.rb b/src/ruby/end2end/killed_client_thread_client.rb
new file mode 100755
index 0000000..d5a7db7
--- /dev/null
+++ b/src/ruby/end2end/killed_client_thread_client.rb
@@ -0,0 +1,58 @@
+#!/usr/bin/env ruby
+
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Attempt to reproduce
+# https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/1327
+
+require_relative './end2end_common'
+
+def main
+ server_port = ''
+ OptionParser.new do |opts|
+ opts.on('--client_control_port=P', String) do
+ STDERR.puts 'client control port not used'
+ end
+ opts.on('--server_port=P', String) do |p|
+ server_port = p
+ end
+ end.parse!
+
+ thd = Thread.new do
+ stub = Echo::EchoServer::Stub.new("localhost:#{server_port}",
+ :this_channel_is_insecure)
+ stub.echo(Echo::EchoRequest.new(request: 'hello'))
+ fail 'the clients rpc in this test shouldnt complete. ' \
+ 'expecting SIGINT to happen in the middle of the call'
+ end
+ thd.join
+end
+
+main
diff --git a/src/ruby/end2end/killed_client_thread_driver.rb b/src/ruby/end2end/killed_client_thread_driver.rb
new file mode 100755
index 0000000..f76d3e1
--- /dev/null
+++ b/src/ruby/end2end/killed_client_thread_driver.rb
@@ -0,0 +1,114 @@
+#!/usr/bin/env ruby
+
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require_relative './end2end_common'
+
+# Service that sleeps for a long time upon receiving an 'echo request'
+# Also, this notifies @call_started_cv once it has received a request.
+class SleepingEchoServerImpl < Echo::EchoServer::Service
+ def initialize(call_started, call_started_mu, call_started_cv)
+ @call_started = call_started
+ @call_started_mu = call_started_mu
+ @call_started_cv = call_started_cv
+ end
+
+ def echo(echo_req, _)
+ @call_started_mu.synchronize do
+ @call_started.set_true
+ @call_started_cv.signal
+ end
+ sleep 1000
+ Echo::EchoReply.new(response: echo_req.request)
+ end
+end
+
+# Mutable boolean
+class BoolHolder
+ attr_reader :val
+
+ def init
+ @val = false
+ end
+
+ def set_true
+ @val = true
+ end
+end
+
+def main
+ STDERR.puts 'start server'
+
+ call_started = BoolHolder.new
+ call_started_mu = Mutex.new
+ call_started_cv = ConditionVariable.new
+
+ service_impl = SleepingEchoServerImpl.new(call_started,
+ call_started_mu,
+ call_started_cv)
+ server_runner = ServerRunner.new(service_impl)
+ server_port = server_runner.run
+
+ STDERR.puts 'start client'
+ _, client_pid = start_client('killed_client_thread_client.rb',
+ server_port)
+
+ call_started_mu.synchronize do
+ call_started_cv.wait(call_started_mu) until call_started.val
+ end
+
+ # SIGINT the child process now that it's
+ # in the middle of an RPC (happening on a non-main thread)
+ Process.kill('SIGINT', client_pid)
+ STDERR.puts 'sent shutdown'
+
+ begin
+ Timeout.timeout(10) do
+ Process.wait(client_pid)
+ end
+ rescue Timeout::Error
+ STDERR.puts "timeout wait for client pid #{client_pid}"
+ Process.kill('SIGKILL', client_pid)
+ Process.wait(client_pid)
+ STDERR.puts 'killed client child'
+ raise 'Timed out waiting for client process. ' \
+ 'It likely hangs when killed while in the middle of an rpc'
+ end
+
+ client_exit_code = $CHILD_STATUS
+ if client_exit_code.termsig != 2 # SIGINT
+ fail 'expected client exit from SIGINT ' \
+ "but got child status: #{client_exit_code}"
+ end
+
+ server_runner.stop
+end
+
+main
diff --git a/src/ruby/end2end/sig_handling_driver.rb b/src/ruby/end2end/sig_handling_driver.rb
index c5d46e0..6691464 100755
--- a/src/ruby/end2end/sig_handling_driver.rb
+++ b/src/ruby/end2end/sig_handling_driver.rb
@@ -36,7 +36,7 @@
def main
STDERR.puts 'start server'
- server_runner = ServerRunner.new
+ server_runner = ServerRunner.new(EchoServerImpl)
server_port = server_runner.run
sleep 1
diff --git a/src/ruby/end2end/sig_int_during_channel_watch_driver.rb b/src/ruby/end2end/sig_int_during_channel_watch_driver.rb
index 84d039b..670cda0 100755
--- a/src/ruby/end2end/sig_int_during_channel_watch_driver.rb
+++ b/src/ruby/end2end/sig_int_during_channel_watch_driver.rb
@@ -36,7 +36,7 @@
def main
STDERR.puts 'start server'
- server_runner = ServerRunner.new
+ server_runner = ServerRunner.new(EchoServerImpl)
server_port = server_runner.run
sleep 1
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 82d340b..344cb94 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -784,7 +784,7 @@
Only one operation of each type can be active at once in any given
batch */
static VALUE grpc_rb_call_run_batch(VALUE self, VALUE ops_hash) {
- run_batch_stack st;
+ run_batch_stack *st = NULL;
grpc_rb_call *call = NULL;
grpc_event ev;
grpc_call_error err;
@@ -792,6 +792,7 @@
VALUE rb_write_flag = rb_ivar_get(self, id_write_flag);
unsigned write_flag = 0;
void *tag = (void*)&st;
+
if (RTYPEDDATA_DATA(self) == NULL) {
rb_raise(grpc_rb_eCallError, "Cannot run batch on closed call");
return Qnil;
@@ -806,14 +807,16 @@
if (rb_write_flag != Qnil) {
write_flag = NUM2UINT(rb_write_flag);
}
- grpc_run_batch_stack_init(&st, write_flag);
- grpc_run_batch_stack_fill_ops(&st, ops_hash);
+ st = gpr_malloc(sizeof(run_batch_stack));
+ grpc_run_batch_stack_init(st, write_flag);
+ grpc_run_batch_stack_fill_ops(st, ops_hash);
/* call grpc_call_start_batch, then wait for it to complete using
* pluck_event */
- err = grpc_call_start_batch(call->wrapped, st.ops, st.op_num, tag, NULL);
+ err = grpc_call_start_batch(call->wrapped, st->ops, st->op_num, tag, NULL);
if (err != GRPC_CALL_OK) {
- grpc_run_batch_stack_cleanup(&st);
+ grpc_run_batch_stack_cleanup(st);
+ gpr_free(st);
rb_raise(grpc_rb_eCallError,
"grpc_call_start_batch failed with %s (code=%d)",
grpc_call_error_detail_of(err), err);
@@ -826,8 +829,9 @@
}
/* Build and return the BatchResult struct result,
if there is an error, it's reflected in the status */
- result = grpc_run_batch_stack_build_result(&st);
- grpc_run_batch_stack_cleanup(&st);
+ result = grpc_run_batch_stack_build_result(st);
+ grpc_run_batch_stack_cleanup(st);
+ gpr_free(st);
return result;
}
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index e7fd0e6..cf69f0c 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -7,9 +7,6 @@
# This file can be regenerated from the template by running
# tools/buildgen/generate_projects.sh
#
- # Additionally, this is currently very experimental, and unsupported.
- # Further work will happen on that file.
- #
# Copyright 2015, Google Inc.
# All rights reserved.
#
@@ -353,7 +350,7 @@
foreach(FIL <%text>${ARGN}</%text>)
get_filename_component(ABS_FIL <%text>${FIL}</%text> ABSOLUTE)
get_filename_component(FIL_WE <%text>${FIL}</%text> NAME_WE)
- file(RELATIVE_PATH REL_FIL <%text>${CMAKE_SOURCE_DIR}</%text> <%text>${ABS_FIL}</%text>)
+ file(RELATIVE_PATH REL_FIL <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text> <%text>${ABS_FIL}</%text>)
get_filename_component(REL_DIR <%text>${REL_FIL}</%text> DIRECTORY)
set(RELFIL_WE "<%text>${REL_DIR}/${FIL_WE}</%text>")
@@ -369,7 +366,7 @@
<%text>${_protobuf_include_path}</%text>
<%text>${REL_FIL}</%text>
DEPENDS <%text>${ABS_FIL}</%text> <%text>${_gRPC_PROTOBUF_PROTOC}</%text> grpc_cpp_plugin
- WORKING_DIRECTORY <%text>${CMAKE_SOURCE_DIR}</%text>
+ WORKING_DIRECTORY <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>
COMMENT "Running gRPC C++ protocol buffer compiler on <%text>${FIL}</%text>"
VERBATIM)
diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template
index 462ea52..80ce643 100644
--- a/templates/grpc.gemspec.template
+++ b/templates/grpc.gemspec.template
@@ -26,7 +26,7 @@
s.files += Dir.glob('include/grpc/**/*')
s.test_files = Dir.glob('src/ruby/spec/**/*')
s.bindir = 'src/ruby/bin'
- s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
+ s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.1'
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index 4870dc1..9a566e6 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -117,10 +117,7 @@
grpc_init();
/* Create endpoints */
- grpc_resource_quota *resource_quota =
- grpc_resource_quota_create("bad_client_test");
- sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
+ sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL);
/* Create server, completion events */
a.server = grpc_server_create(NULL, NULL);
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index 5ace922..424241c 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -96,9 +96,7 @@
f.fixture_data = sfd;
f.cq = grpc_completion_queue_create(NULL);
- grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
- *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
- grpc_resource_quota_unref(resource_quota);
+ *sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL);
return f;
}
diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c
index 3079a42..fe8d766 100644
--- a/test/core/end2end/fixtures/h2_sockpair.c
+++ b/test/core/end2end/fixtures/h2_sockpair.c
@@ -90,9 +90,7 @@
f.fixture_data = sfd;
f.cq = grpc_completion_queue_create(NULL);
- grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
- *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
- grpc_resource_quota_unref(resource_quota);
+ *sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL);
return f;
}
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c
index 70410d7..04174fa 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.c
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c
@@ -90,9 +90,17 @@
f.fixture_data = sfd;
f.cq = grpc_completion_queue_create(NULL);
- grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
- *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 1);
- grpc_resource_quota_unref(resource_quota);
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = 1},
+ {.key = GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = 1},
+ {.key = GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = 1}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ *sfd = grpc_iomgr_create_endpoint_pair("fixture", &args);
return f;
}
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-6312731374256128 b/test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-6312731374256128
new file mode 100644
index 0000000..4c6eb60
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-6312731374256128
Binary files differ
diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c
index 4b98ef2..c8a6077 100644
--- a/test/core/iomgr/endpoint_pair_test.c
+++ b/test/core/iomgr/endpoint_pair_test.c
@@ -49,11 +49,11 @@
size_t slice_size) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_endpoint_test_fixture f;
- grpc_resource_quota *resource_quota =
- grpc_resource_quota_create("endpoint_pair_test");
- grpc_endpoint_pair p =
- grpc_iomgr_create_endpoint_pair("test", resource_quota, slice_size);
- grpc_resource_quota_unref(resource_quota);
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ grpc_endpoint_pair p = grpc_iomgr_create_endpoint_pair("test", &args);
f.client_ep = p.client;
f.server_ep = p.server;
diff --git a/test/core/iomgr/error_test.c b/test/core/iomgr/error_test.c
index 5c60a4d..607dbee 100644
--- a/test/core/iomgr/error_test.c
+++ b/test/core/iomgr/error_test.c
@@ -182,8 +182,6 @@
grpc_error* parent =
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2);
- gpr_log(GPR_DEBUG, "%s", grpc_error_string(parent));
-
for (size_t i = 0; i < 2; ++i) {
GRPC_ERROR_UNREF(children[i]);
}
@@ -216,6 +214,33 @@
GRPC_ERROR_UNREF(error);
}
+static void test_overflow() {
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow");
+
+ for (size_t i = 0; i < 150; ++i) {
+ error = grpc_error_add_child(error,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"));
+ }
+
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 5);
+ error =
+ grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
+ grpc_slice_from_static_string("message for child 2"));
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, 5);
+
+ intptr_t i;
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
+ GPR_ASSERT(i == 5);
+ GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i));
+
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 10);
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
+ GPR_ASSERT(i == 10);
+
+ GRPC_ERROR_UNREF(error);
+ ;
+}
+
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
grpc_init();
@@ -228,6 +253,7 @@
test_create_referencing();
test_create_referencing_many();
test_special();
+ test_overflow();
grpc_shutdown();
return 0;
diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c
index 3dffa02..6ac322b 100644
--- a/test/core/iomgr/fd_conservation_posix_test.c
+++ b/test/core/iomgr/fd_conservation_posix_test.c
@@ -57,7 +57,7 @@
for (i = 0; i < 100; i++) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- p = grpc_iomgr_create_endpoint_pair("test", resource_quota, 1);
+ p = grpc_iomgr_create_endpoint_pair("test", NULL);
grpc_endpoint_destroy(&exec_ctx, p.client);
grpc_endpoint_destroy(&exec_ctx, p.server);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index 5a55be8..2c53a00 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -183,10 +183,12 @@
create_sockets(sv);
- grpc_resource_quota *resource_quota = grpc_resource_quota_create("read_test");
- ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), resource_quota,
- slice_size, "test");
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "read_test"), &args,
+ "test");
grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
written_bytes = fill_socket_partial(sv[0], num_bytes);
@@ -233,11 +235,12 @@
create_sockets(sv);
- grpc_resource_quota *resource_quota =
- grpc_resource_quota_create("large_read_test");
- ep = grpc_tcp_create(grpc_fd_create(sv[1], "large_read_test"), resource_quota,
- slice_size, "test");
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "large_read_test"),
+ &args, "test");
grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
written_bytes = fill_socket(sv[0]);
@@ -372,11 +375,12 @@
create_sockets(sv);
- grpc_resource_quota *resource_quota =
- grpc_resource_quota_create("write_test");
- ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test"), resource_quota,
- GRPC_TCP_DEFAULT_READ_SLICE_SIZE, "test");
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "write_test"), &args,
+ "test");
grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
state.ep = ep;
@@ -441,12 +445,13 @@
create_sockets(sv);
- grpc_resource_quota *resource_quota =
- grpc_resource_quota_create("release_fd_test");
- ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), resource_quota,
- slice_size, "test");
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "read_test"), &args,
+ "test");
GPR_ASSERT(grpc_tcp_fd(ep) == sv[1] && sv[1] >= 0);
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
written_bytes = fill_socket_partial(sv[0], num_bytes);
@@ -534,10 +539,14 @@
create_sockets(sv);
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("tcp_posix_test_socketpair");
- f.client_ep = grpc_tcp_create(grpc_fd_create(sv[0], "fixture:client"),
- resource_quota, slice_size, "test");
- f.server_ep = grpc_tcp_create(grpc_fd_create(sv[1], "fixture:server"),
- resource_quota, slice_size, "test");
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ f.client_ep = grpc_tcp_create(
+ &exec_ctx, grpc_fd_create(sv[0], "fixture:client"), &args, "test");
+ f.server_ep = grpc_tcp_create(
+ &exec_ctx, grpc_fd_create(sv[1], "fixture:server"), &args, "test");
grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset);
grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset);
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index 8f11f98..71d8057 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -39,6 +39,7 @@
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
#include "src/core/lib/iomgr/endpoint_pair.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/security/transport/secure_endpoint.h"
@@ -57,10 +58,11 @@
grpc_endpoint_test_fixture f;
grpc_endpoint_pair tcp;
- grpc_resource_quota *resource_quota =
- grpc_resource_quota_create("secure_endpoint_test");
- tcp = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, slice_size);
- grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
+ grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE,
+ .type = GRPC_ARG_INTEGER,
+ .value.integer = (int)slice_size}};
+ grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+ tcp = grpc_iomgr_create_endpoint_pair("fixture", &args);
grpc_endpoint_add_to_pollset(&exec_ctx, tcp.client, g_pollset);
grpc_endpoint_add_to_pollset(&exec_ctx, tcp.server, g_pollset);
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index d3a83b1..df71777 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -1130,6 +1130,39 @@
EXPECT_TRUE(returned_info.ParseFromString(ToString(iter->second)));
}
+TEST_P(End2endTest, ExpectErrorTest) {
+ ResetStub();
+
+ std::vector<ErrorStatus> expected_status;
+ expected_status.emplace_back();
+ expected_status.back().set_code(13); // INTERNAL
+ expected_status.back().set_error_message("text error message");
+ expected_status.back().set_binary_error_details("text error details");
+ expected_status.emplace_back();
+ expected_status.back().set_code(13); // INTERNAL
+ expected_status.back().set_error_message("text error message");
+ expected_status.back().set_binary_error_details(
+ "\x0\x1\x2\x3\x4\x5\x6\x8\x9\xA\xB");
+
+ for (auto iter = expected_status.begin(); iter != expected_status.end();
+ ++iter) {
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+ request.set_message("Hello");
+ auto* error = request.mutable_param()->mutable_expected_error();
+ error->set_code(iter->code());
+ error->set_error_message(iter->error_message());
+ error->set_binary_error_details(iter->binary_error_details());
+
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_FALSE(s.ok());
+ EXPECT_EQ(iter->code(), s.error_code());
+ EXPECT_EQ(iter->error_message(), s.error_message());
+ EXPECT_EQ(iter->binary_error_details(), s.error_details());
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
// Test with and without a proxy.
class ProxyEnd2endTest : public End2endTest {
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index 11729c4..b473dd1 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -92,6 +92,11 @@
gpr_log(GPR_ERROR, "The request should not reach application handler.");
GPR_ASSERT(0);
}
+ if (request->has_param() && request->param().has_expected_error()) {
+ const auto& error = request->param().expected_error();
+ return Status(static_cast<StatusCode>(error.code()), error.error_message(),
+ error.binary_error_details());
+ }
int server_try_cancel = GetIntValueFromMetadata(
kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL);
if (server_try_cancel > DO_NOT_CANCEL) {
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 3861966..cae3fa1 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -32,16 +32,25 @@
cc_test(
name = "noop-benchmark",
srcs = ["noop-benchmark.cc"],
- deps = ["//external:benchmark"],
linkopts = ["-pthread"],
+ deps = ["//external:benchmark"],
)
cc_library(
name = "helpers",
srcs = ["helpers.cc"],
- hdrs = ["helpers.h", "fullstack_fixtures.h", "fullstack_context_mutators.h"],
- deps = ["//:grpc++", "//external:benchmark", "//test/core/util:grpc_test_util", "//src/proto/grpc/testing:echo_proto"],
+ hdrs = [
+ "fullstack_context_mutators.h",
+ "fullstack_fixtures.h",
+ "helpers.h",
+ ],
linkopts = ["-pthread"],
+ deps = [
+ "//:grpc++",
+ "//external:benchmark",
+ "//src/proto/grpc/testing:echo_proto",
+ "//test/core/util:grpc_test_util",
+ ],
)
cc_test(
@@ -57,6 +66,12 @@
)
cc_test(
+ name = "bm_cq_multiple_threads",
+ srcs = ["bm_cq_multiple_threads.cc"],
+ deps = [":helpers"],
+)
+
+cc_test(
name = "bm_error",
srcs = ["bm_error.cc"],
deps = [":helpers"],
@@ -66,8 +81,8 @@
name = "bm_fullstack_streaming_ping_pong",
srcs = ["bm_fullstack_streaming_ping_pong.cc"],
deps = [":helpers"],
+)
- )
cc_test(
name = "bm_fullstack_streaming_pump",
srcs = ["bm_fullstack_streaming_pump.cc"],
diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
new file mode 100644
index 0000000..8627463
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
@@ -0,0 +1,160 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <benchmark/benchmark.h>
+#include <string.h>
+#include <atomic>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include "test/cpp/microbenchmarks/helpers.h"
+
+extern "C" {
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/port.h"
+#include "src/core/lib/surface/completion_queue.h"
+}
+
+struct grpc_pollset {
+ gpr_mu mu;
+};
+
+namespace grpc {
+namespace testing {
+
+static void* g_tag = (void*)(intptr_t)10; // Some random number
+static grpc_completion_queue* g_cq;
+static grpc_event_engine_vtable g_vtable;
+
+static void pollset_shutdown(grpc_exec_ctx* exec_ctx, grpc_pollset* ps,
+ grpc_closure* closure) {
+ grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
+}
+
+static void pollset_init(grpc_pollset* ps, gpr_mu** mu) {
+ gpr_mu_init(&ps->mu);
+ *mu = &ps->mu;
+}
+
+static void pollset_destroy(grpc_pollset* ps) { gpr_mu_destroy(&ps->mu); }
+
+static grpc_error* pollset_kick(grpc_pollset* p, grpc_pollset_worker* worker) {
+ return GRPC_ERROR_NONE;
+}
+
+/* Callback when the tag is dequeued from the completion queue. Does nothing */
+static void cq_done_cb(grpc_exec_ctx* exec_ctx, void* done_arg,
+ grpc_cq_completion* cq_completion) {
+ gpr_free(cq_completion);
+}
+
+/* Queues a completion tag. ZERO polling overhead */
+static grpc_error* pollset_work(grpc_exec_ctx* exec_ctx, grpc_pollset* ps,
+ grpc_pollset_worker** worker, gpr_timespec now,
+ gpr_timespec deadline) {
+ gpr_mu_unlock(&ps->mu);
+ grpc_cq_begin_op(g_cq, g_tag);
+ grpc_cq_end_op(exec_ctx, g_cq, g_tag, GRPC_ERROR_NONE, cq_done_cb, NULL,
+ (grpc_cq_completion*)gpr_malloc(sizeof(grpc_cq_completion)));
+ grpc_exec_ctx_flush(exec_ctx);
+ gpr_mu_lock(&ps->mu);
+ return GRPC_ERROR_NONE;
+}
+
+static void init_engine_vtable() {
+ memset(&g_vtable, 0, sizeof(g_vtable));
+
+ g_vtable.pollset_size = sizeof(grpc_pollset);
+ g_vtable.pollset_init = pollset_init;
+ g_vtable.pollset_shutdown = pollset_shutdown;
+ g_vtable.pollset_destroy = pollset_destroy;
+ g_vtable.pollset_work = pollset_work;
+ g_vtable.pollset_kick = pollset_kick;
+}
+
+static void setup() {
+ grpc_init();
+ init_engine_vtable();
+ grpc_set_event_engine_test_only(&g_vtable);
+
+ g_cq = grpc_completion_queue_create(NULL);
+}
+
+static void teardown() {
+ grpc_completion_queue_shutdown(g_cq);
+ grpc_completion_queue_destroy(g_cq);
+}
+
+/* A few notes about Multi-threaded benchmarks:
+
+ Setup:
+ The benchmark framework ensures that none of the threads proceed beyond the
+ state.KeepRunning() call unless all the threads have called state.keepRunning
+ atleast once. So it is safe to do the initialization in one of the threads
+ before state.KeepRunning() is called.
+
+ Teardown:
+ The benchmark framework also ensures that no thread is running the benchmark
+ code (i.e the code between two successive calls of state.KeepRunning()) if
+ state.KeepRunning() returns false. So it is safe to do the teardown in one
+ of the threads after state.keepRunning() returns false.
+*/
+static void BM_Cq_Throughput(benchmark::State& state) {
+ TrackCounters track_counters;
+ gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+
+ if (state.thread_index == 0) {
+ setup();
+ }
+
+ while (state.KeepRunning()) {
+ GPR_ASSERT(grpc_completion_queue_next(g_cq, deadline, NULL).type ==
+ GRPC_OP_COMPLETE);
+ }
+
+ state.SetItemsProcessed(state.iterations());
+
+ if (state.thread_index == 0) {
+ teardown();
+ }
+
+ track_counters.Finish(state);
+}
+
+BENCHMARK(BM_Cq_Throughput)->ThreadRange(1, 16)->UseRealTime();
+
+} // namespace testing
+} // namespace grpc
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h
index dc29701..acc56bf 100644
--- a/test/cpp/microbenchmarks/fullstack_fixtures.h
+++ b/test/cpp/microbenchmarks/fullstack_fixtures.h
@@ -212,8 +212,8 @@
class SockPair : public EndpointPairFixture {
public:
SockPair(Service* service)
- : EndpointPairFixture(service, grpc_iomgr_create_endpoint_pair(
- "test", Library::get().rq(), 8192)) {}
+ : EndpointPairFixture(service,
+ grpc_iomgr_create_endpoint_pair("test", NULL)) {}
};
class InProcessCHTTP2 : public EndpointPairFixture {
diff --git a/test/cpp/qps/benchmark_config.cc b/test/cpp/qps/benchmark_config.cc
index 98b8d0b..d33f3e9 100644
--- a/test/cpp/qps/benchmark_config.cc
+++ b/test/cpp/qps/benchmark_config.cc
@@ -33,6 +33,9 @@
#include "test/cpp/qps/benchmark_config.h"
#include <gflags/gflags.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/security/credentials.h>
+#include <grpc/support/log.h>
DEFINE_bool(enable_log_reporter, true,
"Enable reporting of benchmark results through GprLog");
@@ -51,6 +54,11 @@
DEFINE_string(tag, "", "Optional tag for the test");
+DEFINE_string(rpc_reporter_server_address, "",
+ "Server address for rpc reporter to send results to");
+
+DEFINE_bool(enable_rpc_reporter, false, "Enable use of RPC reporter");
+
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
@@ -75,6 +83,13 @@
composite_reporter->add(std::unique_ptr<Reporter>(
new JsonReporter("JsonReporter", FLAGS_scenario_result_file)));
}
+ if (FLAGS_enable_rpc_reporter) {
+ GPR_ASSERT(!FLAGS_rpc_reporter_server_address.empty());
+ composite_reporter->add(std::unique_ptr<Reporter>(new RpcReporter(
+ "RpcReporter",
+ grpc::CreateChannel(FLAGS_rpc_reporter_server_address,
+ grpc::InsecureChannelCredentials()))));
+ }
return std::shared_ptr<Reporter>(composite_reporter);
}
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index 7f84816..a9130bf 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -40,6 +40,9 @@
#include "test/cpp/qps/parse_json.h"
#include "test/cpp/qps/stats.h"
+#include <grpc++/client_context.h>
+#include "src/proto/grpc/testing/services.grpc.pb.h"
+
namespace grpc {
namespace testing {
@@ -142,5 +145,37 @@
// NOP - all reporting is handled by ReportQPS.
}
+void RpcReporter::ReportQPS(const ScenarioResult& result) {
+ grpc::ClientContext context;
+ grpc::Status status;
+ Void dummy;
+
+ gpr_log(GPR_INFO, "RPC reporter sending scenario result to server");
+ status = stub_->ReportScenario(&context, result, &dummy);
+
+ if (status.ok()) {
+ gpr_log(GPR_INFO, "RpcReporter report RPC success!");
+ } else {
+ gpr_log(GPR_ERROR, "RpcReporter report RPC: code: %d. message: %s",
+ status.error_code(), status.error_message().c_str());
+ }
+}
+
+void RpcReporter::ReportQPSPerCore(const ScenarioResult& result) {
+ // NOP - all reporting is handled by ReportQPS.
+}
+
+void RpcReporter::ReportLatency(const ScenarioResult& result) {
+ // NOP - all reporting is handled by ReportQPS.
+}
+
+void RpcReporter::ReportTimes(const ScenarioResult& result) {
+ // NOP - all reporting is handled by ReportQPS.
+}
+
+void RpcReporter::ReportCpuUsage(const ScenarioResult& result) {
+ // NOP - all reporting is handled by ReportQPS.
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index faf87ff..1749be9 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -42,6 +42,9 @@
#include "test/cpp/qps/driver.h"
+#include <grpc++/channel.h>
+#include "src/proto/grpc/testing/services.grpc.pb.h"
+
namespace grpc {
namespace testing {
@@ -124,6 +127,21 @@
const string report_file_;
};
+class RpcReporter : public Reporter {
+ public:
+ RpcReporter(const string& name, std::shared_ptr<grpc::Channel> channel)
+ : Reporter(name), stub_(ReportQpsScenarioService::NewStub(channel)) {}
+
+ private:
+ void ReportQPS(const ScenarioResult& result) override;
+ void ReportQPSPerCore(const ScenarioResult& result) override;
+ void ReportLatency(const ScenarioResult& result) override;
+ void ReportTimes(const ScenarioResult& result) override;
+ void ReportCpuUsage(const ScenarioResult& result) override;
+
+ std::unique_ptr<ReportQpsScenarioService::Stub> stub_;
+};
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc
index 856cd32..c7acb7c 100644
--- a/test/cpp/util/grpc_tool.cc
+++ b/test/cpp/util/grpc_tool.cc
@@ -321,6 +321,7 @@
std::vector<grpc::string> service_list;
if (!desc_db.GetServices(&service_list)) {
+ fprintf(stderr, "Received an error when querying services endpoint.\n");
return false;
}
diff --git a/test/distrib/csharp/run_distrib_test.bat b/test/distrib/csharp/run_distrib_test.bat
index 6cf3811..cb5dd55 100644
--- a/test/distrib/csharp/run_distrib_test.bat
+++ b/test/distrib/csharp/run_distrib_test.bat
@@ -31,7 +31,7 @@
cd /d %~dp0
@rem extract input artifacts
-powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('../../../input_artifacts/csharp_nugets_dotnetcli.zip', 'TestNugetFeed');"
+powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('../../../input_artifacts/csharp_nugets_windows_dotnetcli.zip', 'TestNugetFeed');"
update_version.sh auto
diff --git a/test/distrib/csharp/run_distrib_test.sh b/test/distrib/csharp/run_distrib_test.sh
index 0a77c1a..9de5ce0 100755
--- a/test/distrib/csharp/run_distrib_test.sh
+++ b/test/distrib/csharp/run_distrib_test.sh
@@ -32,7 +32,7 @@
cd $(dirname $0)
-unzip -o "$EXTERNAL_GIT_ROOT/input_artifacts/csharp_nugets_dotnetcli.zip" -d TestNugetFeed
+unzip -o "$EXTERNAL_GIT_ROOT/input_artifacts/csharp_nugets_windows_dotnetcli.zip" -d TestNugetFeed
./update_version.sh auto
diff --git a/test/distrib/csharp/run_distrib_test_dotnetcli.sh b/test/distrib/csharp/run_distrib_test_dotnetcli.sh
index 493c504..cdfc91b 100755
--- a/test/distrib/csharp/run_distrib_test_dotnetcli.sh
+++ b/test/distrib/csharp/run_distrib_test_dotnetcli.sh
@@ -32,7 +32,7 @@
cd $(dirname $0)
-unzip -o "$EXTERNAL_GIT_ROOT/input_artifacts/csharp_nugets_dotnetcli.zip" -d TestNugetFeed
+unzip -o "$EXTERNAL_GIT_ROOT/input_artifacts/csharp_nugets_windows_dotnetcli.zip" -d TestNugetFeed
./update_version.sh auto
diff --git a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
index c6e4aab..02e811f 100755
--- a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
+++ b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
@@ -31,7 +31,7 @@
set -e
# directories to run against
-DIRS="src/core/lib src/core/ext src/cpp test/core test/cpp include src/compiler"
+DIRS="src/core/lib src/core/tsi src/core/ext src/cpp test/core test/cpp include src/compiler"
# file matching patterns to check
GLOB="*.h *.c *.cc"
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index ae5120d..11176d9 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -2566,6 +2566,27 @@
"headers": [],
"is_filegroup": false,
"language": "c++",
+ "name": "bm_cq_multiple_threads",
+ "src": [
+ "test/cpp/microbenchmarks/bm_cq_multiple_threads.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "benchmark",
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc++",
+ "grpc++_test_util",
+ "grpc_benchmark",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c++",
"name": "bm_error",
"src": [
"test/cpp/microbenchmarks/bm_error.cc"
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 88bac79..12d48f2 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -2752,6 +2752,28 @@
"flaky": false,
"gtest": false,
"language": "c++",
+ "name": "bm_cq_multiple_threads",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
+ "--benchmark_min_time=0"
+ ],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c++",
"name": "bm_error",
"platforms": [
"linux",
@@ -150767,6 +150789,29 @@
},
{
"args": [
+ "test/core/end2end/fuzzers/server_fuzzer_corpus/clusterfuzz-testcase-6312731374256128"
+ ],
+ "ci_platforms": [
+ "linux"
+ ],
+ "cpu_cost": 0.1,
+ "exclude_configs": [
+ "tsan"
+ ],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "server_fuzzer_one_entry",
+ "platforms": [
+ "mac",
+ "linux"
+ ],
+ "uses_polling": false
+ },
+ {
+ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/crash-0f4b135c0242669ce425d2662168e9440f8a628d"
],
"ci_platforms": [
diff --git a/tools/run_tests/helper_scripts/pre_build_csharp.bat b/tools/run_tests/helper_scripts/pre_build_csharp.bat
index 99df1c6..bee430a 100644
--- a/tools/run_tests/helper_scripts/pre_build_csharp.bat
+++ b/tools/run_tests/helper_scripts/pre_build_csharp.bat
@@ -43,7 +43,7 @@
mkdir %ARCHITECTURE%
cd %ARCHITECTURE%
@rem TODO(jtattermusch): Stop hardcoding path to yasm once Jenkins workers can locate yasm correctly
-cmake -G "Visual Studio 14 2015" -A %ARCHITECTURE% -DgRPC_BUILD_TESTS=OFF -DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" ../../.. || goto :error
+cmake -G "Visual Studio 14 2015" -A %ARCHITECTURE% -DgRPC_BUILD_TESTS=OFF -DgRPC_MSVC_STATIC_RUNTIME=ON -DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" ../../.. || goto :error
cd ..\..\..
@rem Location of nuget.exe
diff --git a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
index d7da636..92d6975 100755
--- a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
+++ b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
@@ -38,4 +38,5 @@
ruby src/ruby/end2end/channel_state_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/channel_closing_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/sig_int_during_channel_watch_driver.rb || EXIT_CODE=1
+ruby src/ruby/end2end/killed_client_thread_driver.rb || EXIT_CODE=1
exit $EXIT_CODE