Merge remote-tracking branch 'upstream/master' into retry_throttle

pull/9850/head
Mark D. Roth 8 years ago
commit 693d2b48ab
  1. 4
      BUILD
  2. 69
      CMakeLists.txt
  3. 87
      Makefile
  4. 1
      binding.gyp
  5. 38
      build.yaml
  6. 1
      config.m4
  7. 1
      doc/g_stands_for.md
  8. 3
      gRPC-Core.podspec
  9. 2
      grpc.gemspec
  10. 2
      package.xml
  11. 4
      src/core/ext/census/grpc_filter.c
  12. 26
      src/core/ext/client_channel/client_channel.c
  13. 33
      src/core/ext/client_channel/subchannel.c
  14. 18
      src/core/ext/client_channel/subchannel.h
  15. 2
      src/core/ext/load_reporting/load_reporting_filter.c
  16. 33
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  17. 65
      src/core/ext/transport/chttp2/transport/incoming_metadata.c
  18. 18
      src/core/ext/transport/chttp2/transport/incoming_metadata.h
  19. 2
      src/core/ext/transport/chttp2/transport/internal.h
  20. 18
      src/core/ext/transport/chttp2/transport/parsing.c
  21. 48
      src/core/ext/transport/cronet/transport/cronet_transport.c
  22. 36
      src/core/lib/channel/channel_stack.c
  23. 23
      src/core/lib/channel/channel_stack.h
  24. 2
      src/core/lib/channel/compress_filter.c
  25. 6
      src/core/lib/channel/connected_channel.c
  26. 2
      src/core/lib/channel/deadline_filter.c
  27. 2
      src/core/lib/channel/http_client_filter.c
  28. 2
      src/core/lib/channel/http_server_filter.c
  29. 2
      src/core/lib/channel/message_size_filter.c
  30. 2
      src/core/lib/security/transport/client_auth_filter.c
  31. 2
      src/core/lib/security/transport/server_auth_filter.c
  32. 98
      src/core/lib/support/arena.c
  33. 54
      src/core/lib/support/arena.h
  34. 146
      src/core/lib/surface/call.c
  35. 32
      src/core/lib/surface/channel.c
  36. 3
      src/core/lib/surface/channel.h
  37. 4
      src/core/lib/surface/lame_client.c
  38. 2
      src/core/lib/surface/server.c
  39. 2
      src/core/lib/surface/version.c
  40. 12
      src/core/lib/transport/transport.c
  41. 6
      src/core/lib/transport/transport.h
  42. 5
      src/core/lib/transport/transport_impl.h
  43. 3
      src/cpp/common/channel_filter.h
  44. 1
      src/python/grpcio/grpc_core_dependencies.py
  45. 3
      src/python/grpcio_health_checking/grpc_health/v1/health.py
  46. 5
      src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
  47. 2
      templates/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile.template
  48. 16
      test/core/channel/channel_stack_test.c
  49. 2
      test/core/end2end/tests/filter_call_init_fails.c
  50. 2
      test/core/end2end/tests/filter_causes_close.c
  51. 4
      test/core/end2end/tests/filter_latency.c
  52. 2
      test/core/security/BUILD
  53. 14
      test/core/security/ssl_server_fuzzer.c
  54. 139
      test/core/support/arena_test.c
  55. 2
      test/cpp/interop/http2_client.cc
  56. 2
      test/cpp/interop/http2_client.h
  57. 4
      test/cpp/interop/interop_client.cc
  58. 2
      test/cpp/interop/interop_client.h
  59. 4
      test/cpp/interop/interop_server.cc
  60. 4
      test/cpp/interop/reconnect_interop_client.cc
  61. 4
      test/cpp/interop/reconnect_interop_server.cc
  62. 76
      test/cpp/microbenchmarks/bm_arena.cc
  63. 26
      test/cpp/microbenchmarks/bm_call_create.cc
  64. 229
      test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
  65. 2
      test/cpp/qps/client.h
  66. 2
      test/cpp/qps/driver.h
  67. 2
      test/cpp/qps/histogram.h
  68. 4
      test/cpp/qps/server.h
  69. 19
      test/cpp/qps/server_async.cc
  70. 49
      test/http2_test/http2_server_health_check.py
  71. 21
      test/http2_test/http2_test_server.py
  72. 2
      tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
  73. 2
      tools/doxygen/Doxyfile.core.internal
  74. 3
      tools/fuzzer/options/api_fuzzer.options
  75. 3
      tools/fuzzer/options/client_fuzzer.options
  76. 2
      tools/fuzzer/options/fuzzer.options
  77. 2
      tools/fuzzer/options/fuzzer_response.options
  78. 2
      tools/fuzzer/options/fuzzer_serverlist.options
  79. 3
      tools/fuzzer/options/hpack_parser_fuzzer_test.options
  80. 2
      tools/fuzzer/options/percent_decode_fuzzer.options
  81. 2
      tools/fuzzer/options/percent_encode_fuzzer.options
  82. 3
      tools/fuzzer/options/request_fuzzer.options
  83. 3
      tools/fuzzer/options/response_fuzzer.options
  84. 3
      tools/fuzzer/options/server_fuzzer.options
  85. 2
      tools/fuzzer/options/ssl_server_fuzzer.options
  86. 2
      tools/fuzzer/options/uri_fuzzer_test.options
  87. 119
      tools/gcp/utils/gcr_upload.py
  88. 2
      tools/internal_ci/linux/grpc_portability.cfg
  89. 2
      tools/run_tests/generated/configs.json
  90. 39
      tools/run_tests/generated/sources_and_headers.json
  91. 44
      tools/run_tests/generated/tests.json
  92. 20
      tools/run_tests/python_utils/dockerjob.py
  93. 65
      tools/run_tests/run_interop_tests.py
  94. 4
      tools/tsan_suppressions.txt
  95. 7
      tools/ubsan_suppressions.txt
  96. 25
      vsprojects/buildtests_c.sln
  97. 3
      vsprojects/vcxproj/gpr/gpr.vcxproj
  98. 6
      vsprojects/vcxproj/gpr/gpr.vcxproj.filters
  99. 193
      vsprojects/vcxproj/test/arena_test/arena_test.vcxproj
  100. 21
      vsprojects/vcxproj/test/arena_test/arena_test.vcxproj.filters

@ -308,6 +308,7 @@ grpc_cc_library(
srcs = [ srcs = [
"src/core/lib/profiling/basic_timers.c", "src/core/lib/profiling/basic_timers.c",
"src/core/lib/profiling/stap_timers.c", "src/core/lib/profiling/stap_timers.c",
"src/core/lib/support/arena.c",
"src/core/lib/support/alloc.c", "src/core/lib/support/alloc.c",
"src/core/lib/support/atm.c", "src/core/lib/support/atm.c",
"src/core/lib/support/avl.c", "src/core/lib/support/avl.c",
@ -353,6 +354,7 @@ grpc_cc_library(
"src/core/lib/support/wrap_memcpy.c", "src/core/lib/support/wrap_memcpy.c",
], ],
hdrs = [ hdrs = [
"src/core/lib/support/arena.h",
"src/core/lib/profiling/timers.h", "src/core/lib/profiling/timers.h",
"src/core/lib/support/backoff.h", "src/core/lib/support/backoff.h",
"src/core/lib/support/block_annotate.h", "src/core/lib/support/block_annotate.h",
@ -1135,6 +1137,7 @@ grpc_cc_library(
"src/cpp/common/rpc_method.cc", "src/cpp/common/rpc_method.cc",
"src/cpp/common/version_cc.cc", "src/cpp/common/version_cc.cc",
"src/cpp/server/async_generic_service.cc", "src/cpp/server/async_generic_service.cc",
"src/cpp/server/channel_argument_option.cc",
"src/cpp/server/create_default_thread_pool.cc", "src/cpp/server/create_default_thread_pool.cc",
"src/cpp/server/dynamic_thread_pool.cc", "src/cpp/server/dynamic_thread_pool.cc",
"src/cpp/server/health/default_health_check_service.cc", "src/cpp/server/health/default_health_check_service.cc",
@ -1176,6 +1179,7 @@ grpc_cc_library(
"include/grpc++/grpc++.h", "include/grpc++/grpc++.h",
"include/grpc++/health_check_service_interface.h", "include/grpc++/health_check_service_interface.h",
"include/grpc++/impl/call.h", "include/grpc++/impl/call.h",
"include/grpc++/impl/channel_argument_option.h",
"include/grpc++/impl/client_unary_call.h", "include/grpc++/impl/client_unary_call.h",
"include/grpc++/impl/codegen/core_codegen.h", "include/grpc++/impl/codegen/core_codegen.h",
"include/grpc++/impl/grpc_library.h", "include/grpc++/impl/grpc_library.h",

@ -332,6 +332,7 @@ add_dependencies(buildtests_c alarm_test)
add_dependencies(buildtests_c algorithm_test) add_dependencies(buildtests_c algorithm_test)
add_dependencies(buildtests_c alloc_test) add_dependencies(buildtests_c alloc_test)
add_dependencies(buildtests_c alpn_test) add_dependencies(buildtests_c alpn_test)
add_dependencies(buildtests_c arena_test)
add_dependencies(buildtests_c bad_server_response_test) add_dependencies(buildtests_c bad_server_response_test)
add_dependencies(buildtests_c bdp_estimator_test) add_dependencies(buildtests_c bdp_estimator_test)
add_dependencies(buildtests_c bin_decoder_test) add_dependencies(buildtests_c bin_decoder_test)
@ -574,6 +575,9 @@ add_dependencies(buildtests_cxx alarm_cpp_test)
add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx async_end2end_test)
add_dependencies(buildtests_cxx auth_property_iterator_test) add_dependencies(buildtests_cxx auth_property_iterator_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_arena)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_call_create) add_dependencies(buildtests_cxx bm_call_create)
endif() endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -693,6 +697,7 @@ add_library(gpr
src/core/lib/profiling/basic_timers.c src/core/lib/profiling/basic_timers.c
src/core/lib/profiling/stap_timers.c src/core/lib/profiling/stap_timers.c
src/core/lib/support/alloc.c src/core/lib/support/alloc.c
src/core/lib/support/arena.c
src/core/lib/support/atm.c src/core/lib/support/atm.c
src/core/lib/support/avl.c src/core/lib/support/avl.c
src/core/lib/support/backoff.c src/core/lib/support/backoff.c
@ -4120,6 +4125,31 @@ target_link_libraries(alpn_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(arena_test
test/core/support/arena_test.c
)
target_include_directories(arena_test
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 ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(arena_test
${_gRPC_ALLTARGETS_LIBRARIES}
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(bad_server_response_test add_executable(bad_server_response_test
test/core/end2end/bad_server_response_test.c test/core/end2end/bad_server_response_test.c
) )
@ -7634,6 +7664,45 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_arena
test/cpp/microbenchmarks/bm_arena.cc
third_party/googletest/src/gtest-all.cc
)
target_include_directories(bm_arena
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 ${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_arena
${_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_call_create add_executable(bm_call_create
test/cpp/microbenchmarks/bm_call_create.cc test/cpp/microbenchmarks/bm_call_create.cc
third_party/googletest/src/gtest-all.cc third_party/googletest/src/gtest-all.cc

@ -189,7 +189,7 @@ CC_ubsan = clang
CXX_ubsan = clang++ CXX_ubsan = clang++
LD_ubsan = clang LD_ubsan = clang
LDXX_ubsan = clang++ LDXX_ubsan = clang++
CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow
DEFINES_ubsan = NDEBUG DEFINES_ubsan = NDEBUG
@ -906,6 +906,7 @@ algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test
alloc_test: $(BINDIR)/$(CONFIG)/alloc_test alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
alpn_test: $(BINDIR)/$(CONFIG)/alpn_test alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
arena_test: $(BINDIR)/$(CONFIG)/arena_test
bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test
bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
@ -1047,6 +1048,7 @@ wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test
alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
bm_arena: $(BINDIR)/$(CONFIG)/bm_arena
bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create
bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
bm_closure: $(BINDIR)/$(CONFIG)/bm_closure bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
@ -1286,6 +1288,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/algorithm_test \ $(BINDIR)/$(CONFIG)/algorithm_test \
$(BINDIR)/$(CONFIG)/alloc_test \ $(BINDIR)/$(CONFIG)/alloc_test \
$(BINDIR)/$(CONFIG)/alpn_test \ $(BINDIR)/$(CONFIG)/alpn_test \
$(BINDIR)/$(CONFIG)/arena_test \
$(BINDIR)/$(CONFIG)/bad_server_response_test \ $(BINDIR)/$(CONFIG)/bad_server_response_test \
$(BINDIR)/$(CONFIG)/bdp_estimator_test \ $(BINDIR)/$(CONFIG)/bdp_estimator_test \
$(BINDIR)/$(CONFIG)/bin_decoder_test \ $(BINDIR)/$(CONFIG)/bin_decoder_test \
@ -1469,6 +1472,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_arena \
$(BINDIR)/$(CONFIG)/bm_call_create \ $(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_chttp2_hpack \ $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
$(BINDIR)/$(CONFIG)/bm_closure \ $(BINDIR)/$(CONFIG)/bm_closure \
@ -1585,6 +1589,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_arena \
$(BINDIR)/$(CONFIG)/bm_call_create \ $(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_chttp2_hpack \ $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
$(BINDIR)/$(CONFIG)/bm_closure \ $(BINDIR)/$(CONFIG)/bm_closure \
@ -1666,6 +1671,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/alloc_test || ( echo test alloc_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/alloc_test || ( echo test alloc_test failed ; exit 1 )
$(E) "[RUN] Testing alpn_test" $(E) "[RUN] Testing alpn_test"
$(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 )
$(E) "[RUN] Testing arena_test"
$(Q) $(BINDIR)/$(CONFIG)/arena_test || ( echo test arena_test failed ; exit 1 )
$(E) "[RUN] Testing bad_server_response_test" $(E) "[RUN] Testing bad_server_response_test"
$(Q) $(BINDIR)/$(CONFIG)/bad_server_response_test || ( echo test bad_server_response_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bad_server_response_test || ( echo test bad_server_response_test failed ; exit 1 )
$(E) "[RUN] Testing bdp_estimator_test" $(E) "[RUN] Testing bdp_estimator_test"
@ -1926,6 +1933,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing auth_property_iterator_test" $(E) "[RUN] Testing auth_property_iterator_test"
$(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
$(E) "[RUN] Testing bm_arena"
$(Q) $(BINDIR)/$(CONFIG)/bm_arena || ( echo test bm_arena failed ; exit 1 )
$(E) "[RUN] Testing bm_call_create" $(E) "[RUN] Testing bm_call_create"
$(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 )
$(E) "[RUN] Testing bm_chttp2_hpack" $(E) "[RUN] Testing bm_chttp2_hpack"
@ -2599,6 +2608,7 @@ LIBGPR_SRC = \
src/core/lib/profiling/basic_timers.c \ src/core/lib/profiling/basic_timers.c \
src/core/lib/profiling/stap_timers.c \ src/core/lib/profiling/stap_timers.c \
src/core/lib/support/alloc.c \ src/core/lib/support/alloc.c \
src/core/lib/support/arena.c \
src/core/lib/support/atm.c \ src/core/lib/support/atm.c \
src/core/lib/support/avl.c \ src/core/lib/support/avl.c \
src/core/lib/support/backoff.c \ src/core/lib/support/backoff.c \
@ -8104,6 +8114,38 @@ endif
endif endif
ARENA_TEST_SRC = \
test/core/support/arena_test.c \
ARENA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ARENA_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/arena_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/arena_test: $(ARENA_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(ARENA_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/arena_test
endif
$(OBJDIR)/$(CONFIG)/test/core/support/arena_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_arena_test: $(ARENA_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(ARENA_TEST_OBJS:.o=.dep)
endif
endif
BAD_SERVER_RESPONSE_TEST_SRC = \ BAD_SERVER_RESPONSE_TEST_SRC = \
test/core/end2end/bad_server_response_test.c \ test/core/end2end/bad_server_response_test.c \
@ -12649,6 +12691,49 @@ endif
endif endif
BM_ARENA_SRC = \
test/cpp/microbenchmarks/bm_arena.cc \
BM_ARENA_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_ARENA_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_arena: 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_arena: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_arena: $(PROTOBUF_DEP) $(BM_ARENA_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_ARENA_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_arena
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_arena.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_arena: $(BM_ARENA_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_ARENA_OBJS:.o=.dep)
endif
endif
BM_CALL_CREATE_SRC = \ BM_CALL_CREATE_SRC = \
test/cpp/microbenchmarks/bm_call_create.cc \ test/cpp/microbenchmarks/bm_call_create.cc \

@ -544,6 +544,7 @@
'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/basic_timers.c',
'src/core/lib/profiling/stap_timers.c', 'src/core/lib/profiling/stap_timers.c',
'src/core/lib/support/alloc.c', 'src/core/lib/support/alloc.c',
'src/core/lib/support/arena.c',
'src/core/lib/support/atm.c', 'src/core/lib/support/atm.c',
'src/core/lib/support/avl.c', 'src/core/lib/support/avl.c',
'src/core/lib/support/backoff.c', 'src/core/lib/support/backoff.c',

@ -13,7 +13,7 @@ settings:
'#09': Per-language overrides are possible with (eg) ruby_version tag here '#09': Per-language overrides are possible with (eg) ruby_version tag here
'#10': See the expand_version.py for all the quirks here '#10': See the expand_version.py for all the quirks here
core_version: 3.0.0-dev core_version: 3.0.0-dev
g_stands_for: green g_stands_for: gentle
version: 1.3.0-dev version: 1.3.0-dev
filegroups: filegroups:
- name: census - name: census
@ -85,6 +85,7 @@ filegroups:
- include/grpc/support/useful.h - include/grpc/support/useful.h
headers: headers:
- src/core/lib/profiling/timers.h - src/core/lib/profiling/timers.h
- src/core/lib/support/arena.h
- src/core/lib/support/backoff.h - src/core/lib/support/backoff.h
- src/core/lib/support/block_annotate.h - src/core/lib/support/block_annotate.h
- src/core/lib/support/env.h - src/core/lib/support/env.h
@ -101,6 +102,7 @@ filegroups:
- src/core/lib/profiling/basic_timers.c - src/core/lib/profiling/basic_timers.c
- src/core/lib/profiling/stap_timers.c - src/core/lib/profiling/stap_timers.c
- src/core/lib/support/alloc.c - src/core/lib/support/alloc.c
- src/core/lib/support/arena.c
- src/core/lib/support/atm.c - src/core/lib/support/atm.c
- src/core/lib/support/avl.c - src/core/lib/support/avl.c
- src/core/lib/support/backoff.c - src/core/lib/support/backoff.c
@ -1486,6 +1488,14 @@ targets:
- test/core/end2end/fuzzers/api_fuzzer_corpus - test/core/end2end/fuzzers/api_fuzzer_corpus
dict: test/core/end2end/fuzzers/api_fuzzer.dictionary dict: test/core/end2end/fuzzers/api_fuzzer.dictionary
maxlen: 2048 maxlen: 2048
- name: arena_test
build: test
language: c
src:
- test/core/support/arena_test.c
deps:
- gpr_test_util
- gpr
- name: bad_server_response_test - name: bad_server_response_test
build: test build: test
language: c language: c
@ -3057,6 +3067,26 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: bm_arena
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_arena.cc
deps:
- grpc_benchmark
- benchmark
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
args:
- --benchmark_min_time=0
platforms:
- mac
- linux
- posix
- name: bm_call_create - name: bm_call_create
build: test build: test
language: c++ language: c++
@ -4258,8 +4288,8 @@ configs:
TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1 TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
ubsan: ubsan:
CC: clang CC: clang
CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer
-fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs -Wno-unused-command-line-argument -Wvarargs
CXX: clang++ CXX: clang++
DEFINES: NDEBUG DEFINES: NDEBUG
LD: clang LD: clang
@ -4267,7 +4297,7 @@ configs:
LDXX: clang++ LDXX: clang++
compile_the_world: true compile_the_world: true
test_environ: test_environ:
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1 UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt
defaults: defaults:
benchmark: benchmark:
CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX

@ -39,6 +39,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/profiling/basic_timers.c \ src/core/lib/profiling/basic_timers.c \
src/core/lib/profiling/stap_timers.c \ src/core/lib/profiling/stap_timers.c \
src/core/lib/support/alloc.c \ src/core/lib/support/alloc.c \
src/core/lib/support/arena.c \
src/core/lib/support/atm.c \ src/core/lib/support/atm.c \
src/core/lib/support/avl.c \ src/core/lib/support/avl.c \
src/core/lib/support/backoff.c \ src/core/lib/support/backoff.c \

@ -7,3 +7,4 @@ future), and the corresponding version numbers that used them:
- 1.0 'g' stands for 'gRPC' - 1.0 'g' stands for 'gRPC'
- 1.1 'g' stands for 'good' - 1.1 'g' stands for 'good'
- 1.2 'g' stands for 'green' - 1.2 'g' stands for 'green'
- 1.3 'g' stands for 'gentle'

@ -196,6 +196,7 @@ Pod::Spec.new do |s|
# To save you from scrolling, this is the last part of the podspec. # To save you from scrolling, this is the last part of the podspec.
ss.source_files = 'src/core/lib/profiling/timers.h', ss.source_files = 'src/core/lib/profiling/timers.h',
'src/core/lib/support/arena.h',
'src/core/lib/support/backoff.h', 'src/core/lib/support/backoff.h',
'src/core/lib/support/block_annotate.h', 'src/core/lib/support/block_annotate.h',
'src/core/lib/support/env.h', 'src/core/lib/support/env.h',
@ -211,6 +212,7 @@ Pod::Spec.new do |s|
'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/basic_timers.c',
'src/core/lib/profiling/stap_timers.c', 'src/core/lib/profiling/stap_timers.c',
'src/core/lib/support/alloc.c', 'src/core/lib/support/alloc.c',
'src/core/lib/support/arena.c',
'src/core/lib/support/atm.c', 'src/core/lib/support/atm.c',
'src/core/lib/support/avl.c', 'src/core/lib/support/avl.c',
'src/core/lib/support/backoff.c', 'src/core/lib/support/backoff.c',
@ -678,6 +680,7 @@ Pod::Spec.new do |s|
'src/core/plugin_registry/grpc_plugin_registry.c' 'src/core/plugin_registry/grpc_plugin_registry.c'
ss.private_header_files = 'src/core/lib/profiling/timers.h', ss.private_header_files = 'src/core/lib/profiling/timers.h',
'src/core/lib/support/arena.h',
'src/core/lib/support/backoff.h', 'src/core/lib/support/backoff.h',
'src/core/lib/support/block_annotate.h', 'src/core/lib/support/block_annotate.h',
'src/core/lib/support/env.h', 'src/core/lib/support/env.h',

@ -82,6 +82,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_posix.h )
s.files += %w( include/grpc/impl/codegen/sync_windows.h ) s.files += %w( include/grpc/impl/codegen/sync_windows.h )
s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/profiling/timers.h )
s.files += %w( src/core/lib/support/arena.h )
s.files += %w( src/core/lib/support/backoff.h ) s.files += %w( src/core/lib/support/backoff.h )
s.files += %w( src/core/lib/support/block_annotate.h ) s.files += %w( src/core/lib/support/block_annotate.h )
s.files += %w( src/core/lib/support/env.h ) s.files += %w( src/core/lib/support/env.h )
@ -97,6 +98,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/profiling/basic_timers.c ) s.files += %w( src/core/lib/profiling/basic_timers.c )
s.files += %w( src/core/lib/profiling/stap_timers.c ) s.files += %w( src/core/lib/profiling/stap_timers.c )
s.files += %w( src/core/lib/support/alloc.c ) s.files += %w( src/core/lib/support/alloc.c )
s.files += %w( src/core/lib/support/arena.c )
s.files += %w( src/core/lib/support/atm.c ) s.files += %w( src/core/lib/support/atm.c )
s.files += %w( src/core/lib/support/avl.c ) s.files += %w( src/core/lib/support/avl.c )
s.files += %w( src/core/lib/support/backoff.c ) s.files += %w( src/core/lib/support/backoff.c )

@ -91,6 +91,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/profiling/timers.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/profiling/timers.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/arena.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/backoff.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/backoff.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/block_annotate.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/block_annotate.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" />
@ -106,6 +107,7 @@
<file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/profiling/stap_timers.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/profiling/stap_timers.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/alloc.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/alloc.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/arena.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/atm.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/atm.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/avl.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/avl.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/backoff.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/backoff.c" role="src" />

@ -138,7 +138,7 @@ static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
call_data *d = elem->call_data; call_data *d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc client stats and census_rpc_end_op here */ /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
@ -160,7 +160,7 @@ static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
call_data *d = elem->call_data; call_data *d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc server stats and census_tracing_end_op here */ /* TODO(hongyu): record rpc server stats and census_tracing_end_op here */

@ -747,6 +747,7 @@ typedef struct client_channel_call_data {
/** either 0 for no call, 1 for cancelled, or a pointer to a /** either 0 for no call, 1 for cancelled, or a pointer to a
grpc_subchannel_call */ grpc_subchannel_call */
gpr_atm subchannel_call; gpr_atm subchannel_call;
gpr_arena *arena;
subchannel_creation_phase creation_phase; subchannel_creation_phase creation_phase;
grpc_connected_subchannel *connected_subchannel; grpc_connected_subchannel *connected_subchannel;
@ -889,9 +890,14 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
} else { } else {
/* Create call on subchannel. */ /* Create call on subchannel. */
grpc_subchannel_call *subchannel_call = NULL; grpc_subchannel_call *subchannel_call = NULL;
const grpc_connected_subchannel_call_args call_args = {
.pollent = calld->pollent,
.path = calld->path,
.start_time = calld->call_start_time,
.deadline = calld->deadline,
.arena = calld->arena};
grpc_error *new_error = grpc_connected_subchannel_create_call( grpc_error *new_error = grpc_connected_subchannel_create_call(
exec_ctx, calld->connected_subchannel, calld->pollent, calld->path, exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
calld->call_start_time, calld->deadline, &subchannel_call);
if (new_error != GRPC_ERROR_NONE) { if (new_error != GRPC_ERROR_NONE) {
new_error = grpc_error_add_child(new_error, error); new_error = grpc_error_add_child(new_error, error);
subchannel_call = CANCELLED_CALL; subchannel_call = CANCELLED_CALL;
@ -1118,9 +1124,14 @@ static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
calld->connected_subchannel != NULL) { calld->connected_subchannel != NULL) {
grpc_subchannel_call *subchannel_call = NULL; grpc_subchannel_call *subchannel_call = NULL;
const grpc_connected_subchannel_call_args call_args = {
.pollent = calld->pollent,
.path = calld->path,
.start_time = calld->call_start_time,
.deadline = calld->deadline,
.arena = calld->arena};
grpc_error *error = grpc_connected_subchannel_create_call( grpc_error *error = grpc_connected_subchannel_create_call(
exec_ctx, calld->connected_subchannel, calld->pollent, calld->path, exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
calld->call_start_time, calld->deadline, &subchannel_call);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
subchannel_call = CANCELLED_CALL; subchannel_call = CANCELLED_CALL;
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error)); fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
@ -1235,6 +1246,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
calld->call_start_time = args->start_time; calld->call_start_time = args->start_time;
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC); calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
calld->owning_call = args->call_stack; calld->owning_call = args->call_stack;
calld->arena = args->arena;
grpc_deadline_state_start(exec_ctx, elem, calld->deadline); grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -1243,7 +1255,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *then_schedule_closure) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_deadline_state_destroy(exec_ctx, elem); grpc_deadline_state_destroy(exec_ctx, elem);
grpc_slice_unref_internal(exec_ctx, calld->path); grpc_slice_unref_internal(exec_ctx, calld->path);
@ -1253,6 +1265,8 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(calld->cancel_error); GRPC_ERROR_UNREF(calld->cancel_error);
grpc_subchannel_call *call = GET_CALL(calld); grpc_subchannel_call *call = GET_CALL(calld);
if (call != NULL && call != CANCELLED_CALL) { if (call != NULL && call != CANCELLED_CALL) {
grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure);
then_schedule_closure = NULL;
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
} }
GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING); GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
@ -1262,7 +1276,7 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
"picked"); "picked");
} }
gpr_free(calld->waiting_ops); gpr_free(calld->waiting_ops);
gpr_free(and_free_memory); grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
} }
static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,

@ -148,6 +148,7 @@ struct grpc_subchannel {
struct grpc_subchannel_call { struct grpc_subchannel_call {
grpc_connected_subchannel *connection; grpc_connected_subchannel *connection;
grpc_closure *schedule_closure_after_destroy;
}; };
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1)) #define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
@ -719,13 +720,22 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call, static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
grpc_error *error) { grpc_error *error) {
grpc_subchannel_call *c = call; grpc_subchannel_call *c = call;
GPR_ASSERT(c->schedule_closure_after_destroy != NULL);
GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0); GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
grpc_connected_subchannel *connection = c->connection; grpc_connected_subchannel *connection = c->connection;
grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), NULL, c); grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), NULL,
c->schedule_closure_after_destroy);
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, connection, "subchannel_call"); GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, connection, "subchannel_call");
GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0); GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
} }
void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call *call,
grpc_closure *closure) {
GPR_ASSERT(call->schedule_closure_after_destroy == NULL);
GPR_ASSERT(closure != NULL);
call->schedule_closure_after_destroy = closure;
}
void grpc_subchannel_call_ref( void grpc_subchannel_call_ref(
grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
@ -761,15 +771,22 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
grpc_error *grpc_connected_subchannel_create_call( grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time, const grpc_connected_subchannel_call_args *args,
gpr_timespec deadline, grpc_subchannel_call **call) { grpc_subchannel_call **call) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
*call = gpr_zalloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); *call = gpr_arena_alloc(
args->arena, sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
(*call)->connection = con; // Ref is added below. (*call)->connection = con; // Ref is added below.
grpc_error *error = const grpc_call_element_args call_args = {.call_stack = callstk,
grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, *call, .server_transport_data = NULL,
NULL, NULL, path, start_time, deadline, callstk); .context = NULL,
.path = args->path,
.start_time = args->start_time,
.deadline = args->deadline,
.arena = args->arena};
grpc_error *error = grpc_call_stack_init(
exec_ctx, chanstk, 1, subchannel_call_destroy, *call, &call_args);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
const char *error_string = grpc_error_string(error); const char *error_string = grpc_error_string(error);
gpr_log(GPR_ERROR, "error: %s", error_string); gpr_log(GPR_ERROR, "error: %s", error_string);
@ -778,7 +795,7 @@ grpc_error *grpc_connected_subchannel_create_call(
return error; return error;
} }
GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call"); GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, pollent); grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, args->pollent);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -37,6 +37,7 @@
#include "src/core/ext/client_channel/connector.h" #include "src/core/ext/client_channel/connector.h"
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/support/arena.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
@ -112,10 +113,18 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
GRPC_SUBCHANNEL_REF_EXTRA_ARGS); GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
/** construct a subchannel call */ /** construct a subchannel call */
typedef struct {
grpc_polling_entity *pollent;
grpc_slice path;
gpr_timespec start_time;
gpr_timespec deadline;
gpr_arena *arena;
} grpc_connected_subchannel_call_args;
grpc_error *grpc_connected_subchannel_create_call( grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel, grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time, const grpc_connected_subchannel_call_args *args,
gpr_timespec deadline, grpc_subchannel_call **subchannel_call); grpc_subchannel_call **subchannel_call);
/** process a transport level op */ /** process a transport level op */
void grpc_connected_subchannel_process_transport_op( void grpc_connected_subchannel_process_transport_op(
@ -154,6 +163,11 @@ void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx, char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *subchannel_call); grpc_subchannel_call *subchannel_call);
/** Must be called once per call. Sets the 'then_schedule_closure' argument for
call stack destruction. */
void grpc_subchannel_call_set_cleanup_closure(
grpc_subchannel_call *subchannel_call, grpc_closure *closure);
grpc_call_stack *grpc_subchannel_call_get_call_stack( grpc_call_stack *grpc_subchannel_call_get_call_stack(
grpc_subchannel_call *subchannel_call); grpc_subchannel_call *subchannel_call);

@ -123,7 +123,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
/* TODO(dgq): do something with the data /* TODO(dgq): do something with the data

@ -575,7 +575,7 @@ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s) {
static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_stream_refcount *refcount, grpc_stream *gs, grpc_stream_refcount *refcount,
const void *server_data) { const void *server_data, gpr_arena *arena) {
GPR_TIMER_BEGIN("init_stream", 0); GPR_TIMER_BEGIN("init_stream", 0);
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
@ -588,8 +588,8 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
gpr_ref_init(&s->active_streams, 1); gpr_ref_init(&s->active_streams, 1);
GRPC_CHTTP2_STREAM_REF(s, "chttp2"); GRPC_CHTTP2_STREAM_REF(s, "chttp2");
grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0]); grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0], arena);
grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1]); grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1], arena);
grpc_chttp2_data_parser_init(&s->data_parser); grpc_chttp2_data_parser_init(&s->data_parser);
grpc_slice_buffer_init(&s->flow_controlled_buffer); grpc_slice_buffer_init(&s->flow_controlled_buffer);
s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
@ -665,16 +665,17 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
GPR_TIMER_END("destroy_stream", 0); GPR_TIMER_END("destroy_stream", 0);
gpr_free(s->destroy_stream_arg); grpc_closure_sched(exec_ctx, s->destroy_stream_arg, GRPC_ERROR_NONE);
} }
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, void *and_free_memory) { grpc_stream *gs,
grpc_closure *then_schedule_closure) {
GPR_TIMER_BEGIN("destroy_stream", 0); GPR_TIMER_BEGIN("destroy_stream", 0);
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
s->destroy_stream_arg = and_free_memory; s->destroy_stream_arg = then_schedule_closure;
grpc_closure_sched( grpc_closure_sched(
exec_ctx, grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s, exec_ctx, grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s,
grpc_combiner_scheduler(t->combiner, false)), grpc_combiner_scheduler(t->combiner, false)),
@ -1629,15 +1630,19 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
s->recv_trailing_metadata_finished != NULL) { s->recv_trailing_metadata_finished != NULL) {
char status_string[GPR_LTOA_MIN_BUFSIZE]; char status_string[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(status, status_string); gpr_ltoa(status, status_string);
grpc_chttp2_incoming_metadata_buffer_replace_or_add( GRPC_LOG_IF_ERROR("add_status",
exec_ctx, &s->metadata_buffer[1], grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS, exec_ctx, &s->metadata_buffer[1],
grpc_slice_from_copied_string(status_string))); grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_STATUS,
grpc_slice_from_copied_string(status_string))));
if (msg != NULL) { if (msg != NULL) {
grpc_chttp2_incoming_metadata_buffer_replace_or_add( GRPC_LOG_IF_ERROR(
exec_ctx, &s->metadata_buffer[1], "add_status_message",
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_slice_from_copied_string(msg))); exec_ctx, &s->metadata_buffer[1],
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
grpc_slice_from_copied_string(msg))));
} }
s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);

@ -41,69 +41,48 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
void grpc_chttp2_incoming_metadata_buffer_init( void grpc_chttp2_incoming_metadata_buffer_init(
grpc_chttp2_incoming_metadata_buffer *buffer) { grpc_chttp2_incoming_metadata_buffer *buffer, gpr_arena *arena) {
buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); buffer->arena = arena;
grpc_metadata_batch_init(&buffer->batch);
buffer->batch.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
} }
void grpc_chttp2_incoming_metadata_buffer_destroy( void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer) { grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer) {
size_t i; grpc_metadata_batch_destroy(exec_ctx, &buffer->batch);
if (!buffer->published) {
for (i = 0; i < buffer->count; i++) {
GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md);
}
}
gpr_free(buffer->elems);
} }
void grpc_chttp2_incoming_metadata_buffer_add( grpc_error *grpc_chttp2_incoming_metadata_buffer_add(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) { grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
GPR_ASSERT(!buffer->published); grpc_mdelem elem) {
if (buffer->capacity == buffer->count) {
buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
buffer->elems =
gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity);
}
buffer->elems[buffer->count++].md = elem;
buffer->size += GRPC_MDELEM_LENGTH(elem); buffer->size += GRPC_MDELEM_LENGTH(elem);
return grpc_metadata_batch_add_tail(
exec_ctx, &buffer->batch,
gpr_arena_alloc(buffer->arena, sizeof(grpc_linked_mdelem)), elem);
} }
void grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_mdelem elem) { grpc_mdelem elem) {
for (size_t i = 0; i < buffer->count; i++) { for (grpc_linked_mdelem *l = buffer->batch.list.head; l != NULL;
if (grpc_slice_eq(GRPC_MDKEY(buffer->elems[i].md), GRPC_MDKEY(elem))) { l = l->next) {
GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md); if (grpc_slice_eq(GRPC_MDKEY(l->md), GRPC_MDKEY(elem))) {
buffer->elems[i].md = elem; GRPC_MDELEM_UNREF(exec_ctx, l->md);
return; l->md = elem;
return GRPC_ERROR_NONE;
} }
} }
grpc_chttp2_incoming_metadata_buffer_add(buffer, elem); return grpc_chttp2_incoming_metadata_buffer_add(exec_ctx, buffer, elem);
} }
void grpc_chttp2_incoming_metadata_buffer_set_deadline( void grpc_chttp2_incoming_metadata_buffer_set_deadline(
grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) { grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
GPR_ASSERT(!buffer->published); buffer->batch.deadline = deadline;
buffer->deadline = deadline;
} }
void grpc_chttp2_incoming_metadata_buffer_publish( void grpc_chttp2_incoming_metadata_buffer_publish(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_metadata_batch *batch) { grpc_metadata_batch *batch) {
GPR_ASSERT(!buffer->published); *batch = buffer->batch;
buffer->published = 1; grpc_metadata_batch_init(&buffer->batch);
if (buffer->count > 0) {
size_t i;
for (i = 0; i < buffer->count; i++) {
/* TODO(ctiller): do something better here */
if (!GRPC_LOG_IF_ERROR("grpc_chttp2_incoming_metadata_buffer_publish",
grpc_metadata_batch_link_tail(
exec_ctx, batch, &buffer->elems[i]))) {
GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md);
}
}
} else {
batch->list.head = batch->list.tail = NULL;
}
batch->deadline = buffer->deadline;
} }

@ -37,28 +37,26 @@
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
typedef struct { typedef struct {
grpc_linked_mdelem *elems; gpr_arena *arena;
size_t count; grpc_metadata_batch batch;
size_t capacity;
gpr_timespec deadline;
int published;
size_t size; // total size of metadata size_t size; // total size of metadata
} grpc_chttp2_incoming_metadata_buffer; } grpc_chttp2_incoming_metadata_buffer;
/** assumes everything initially zeroed */ /** assumes everything initially zeroed */
void grpc_chttp2_incoming_metadata_buffer_init( void grpc_chttp2_incoming_metadata_buffer_init(
grpc_chttp2_incoming_metadata_buffer *buffer); grpc_chttp2_incoming_metadata_buffer *buffer, gpr_arena *arena);
void grpc_chttp2_incoming_metadata_buffer_destroy( void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer); grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer);
void grpc_chttp2_incoming_metadata_buffer_publish( void grpc_chttp2_incoming_metadata_buffer_publish(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_metadata_batch *batch); grpc_metadata_batch *batch);
void grpc_chttp2_incoming_metadata_buffer_add( grpc_error *grpc_chttp2_incoming_metadata_buffer_add(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem);
void grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_mdelem elem); grpc_mdelem elem) GRPC_MUST_USE_RESULT;
grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_mdelem elem) GRPC_MUST_USE_RESULT;
void grpc_chttp2_incoming_metadata_buffer_set_deadline( void grpc_chttp2_incoming_metadata_buffer_set_deadline(
grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline); grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline);

@ -425,7 +425,7 @@ struct grpc_chttp2_stream {
grpc_stream_refcount *refcount; grpc_stream_refcount *refcount;
grpc_closure destroy_stream; grpc_closure destroy_stream;
void *destroy_stream_arg; grpc_closure *destroy_stream_arg;
grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
uint8_t included[STREAM_LIST_COUNT]; uint8_t included[STREAM_LIST_COUNT];

@ -548,7 +548,14 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
s->seen_error = true; s->seen_error = true;
GRPC_MDELEM_UNREF(exec_ctx, md); GRPC_MDELEM_UNREF(exec_ctx, md);
} else { } else {
grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md); grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add(
exec_ctx, &s->metadata_buffer[0], md);
if (error != GRPC_ERROR_NONE) {
grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
s->seen_error = true;
GRPC_MDELEM_UNREF(exec_ctx, md);
}
} }
} }
@ -598,7 +605,14 @@ static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
s->seen_error = true; s->seen_error = true;
GRPC_MDELEM_UNREF(exec_ctx, md); GRPC_MDELEM_UNREF(exec_ctx, md);
} else { } else {
grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md); grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add(
exec_ctx, &s->metadata_buffer[1], md);
if (error != GRPC_ERROR_NONE) {
grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
s->seen_error = true;
GRPC_MDELEM_UNREF(exec_ctx, md);
}
} }
GPR_TIMER_END("on_trailing_header", 0); GPR_TIMER_END("on_trailing_header", 0);

@ -184,6 +184,7 @@ struct op_storage {
}; };
struct stream_obj { struct stream_obj {
gpr_arena *arena;
struct op_and_state *oas; struct op_and_state *oas;
grpc_transport_stream_op *curr_op; grpc_transport_stream_op *curr_op;
grpc_cronet_transport *curr_ct; grpc_cronet_transport *curr_ct;
@ -272,7 +273,7 @@ static void maybe_flush_read(stream_obj *s) {
/* Whenever the evaluation of any of the two condition is changed, we check /* Whenever the evaluation of any of the two condition is changed, we check
* whether we should enter the flush read state. */ * whether we should enter the flush read state. */
if (s->state.pending_recv_trailing_metadata && s->state.fail_state) { if (s->state.pending_recv_trailing_metadata && s->state.fail_state) {
if (!s->state.flush_read) { if (!s->state.flush_read && !s->state.rs.read_stream_closed) {
CRONET_LOG(GPR_DEBUG, "%p: Flush read", s); CRONET_LOG(GPR_DEBUG, "%p: Flush read", s);
s->state.flush_read = true; s->state.flush_read = true;
null_and_maybe_free_read_buffer(s); null_and_maybe_free_read_buffer(s);
@ -486,15 +487,18 @@ static void on_response_headers_received(
gpr_mu_lock(&s->mu); gpr_mu_lock(&s->mu);
memset(&s->state.rs.initial_metadata, 0, memset(&s->state.rs.initial_metadata, 0,
sizeof(s->state.rs.initial_metadata)); sizeof(s->state.rs.initial_metadata));
grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata); grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata,
s->arena);
for (size_t i = 0; i < headers->count; i++) { for (size_t i = 0; i < headers->count; i++) {
grpc_chttp2_incoming_metadata_buffer_add( GRPC_LOG_IF_ERROR(
&s->state.rs.initial_metadata, "on_response_headers_received",
grpc_mdelem_from_slices( grpc_chttp2_incoming_metadata_buffer_add(
&exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( &exec_ctx, &s->state.rs.initial_metadata,
headers->headers[i].key)), grpc_mdelem_from_slices(
grpc_slice_intern( &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(
grpc_slice_from_static_string(headers->headers[i].value)))); headers->headers[i].key)),
grpc_slice_intern(grpc_slice_from_static_string(
headers->headers[i].value)))));
} }
s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true; s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true;
if (!(s->state.state_op_done[OP_CANCEL_ERROR] || if (!(s->state.state_op_done[OP_CANCEL_ERROR] ||
@ -586,17 +590,20 @@ static void on_response_trailers_received(
memset(&s->state.rs.trailing_metadata, 0, memset(&s->state.rs.trailing_metadata, 0,
sizeof(s->state.rs.trailing_metadata)); sizeof(s->state.rs.trailing_metadata));
s->state.rs.trailing_metadata_valid = false; s->state.rs.trailing_metadata_valid = false;
grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata); grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata,
s->arena);
for (size_t i = 0; i < trailers->count; i++) { for (size_t i = 0; i < trailers->count; i++) {
CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key, CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key,
trailers->headers[i].value); trailers->headers[i].value);
grpc_chttp2_incoming_metadata_buffer_add( GRPC_LOG_IF_ERROR(
&s->state.rs.trailing_metadata, "on_response_trailers_received",
grpc_mdelem_from_slices( grpc_chttp2_incoming_metadata_buffer_add(
&exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( &exec_ctx, &s->state.rs.trailing_metadata,
trailers->headers[i].key)), grpc_mdelem_from_slices(
grpc_slice_intern( &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(
grpc_slice_from_static_string(trailers->headers[i].value)))); trailers->headers[i].key)),
grpc_slice_intern(grpc_slice_from_static_string(
trailers->headers[i].value)))));
s->state.rs.trailing_metadata_valid = true; s->state.rs.trailing_metadata_valid = true;
if (0 == strcmp(trailers->headers[i].key, "grpc-status") && if (0 == strcmp(trailers->headers[i].key, "grpc-status") &&
0 != strcmp(trailers->headers[i].value, "0")) { 0 != strcmp(trailers->headers[i].value, "0")) {
@ -1215,7 +1222,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_stream_refcount *refcount, grpc_stream *gs, grpc_stream_refcount *refcount,
const void *server_data) { const void *server_data, gpr_arena *arena) {
stream_obj *s = (stream_obj *)gs; stream_obj *s = (stream_obj *)gs;
memset(&s->storage, 0, sizeof(s->storage)); memset(&s->storage, 0, sizeof(s->storage));
s->storage.head = NULL; s->storage.head = NULL;
@ -1237,6 +1244,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
s->curr_gs = gs; s->curr_gs = gs;
s->curr_ct = (grpc_cronet_transport *)gt; s->curr_ct = (grpc_cronet_transport *)gt;
s->arena = arena;
gpr_mu_init(&s->mu); gpr_mu_init(&s->mu);
return 0; return 0;
@ -1273,10 +1281,12 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
} }
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, void *and_free_memory) { grpc_stream *gs,
grpc_closure *then_schedule_closure) {
stream_obj *s = (stream_obj *)gs; stream_obj *s = (stream_obj *)gs;
null_and_maybe_free_read_buffer(s); null_and_maybe_free_read_buffer(s);
GRPC_ERROR_UNREF(s->state.cancel_error); GRPC_ERROR_UNREF(s->state.cancel_error);
grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
} }
static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {} static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {}

@ -166,41 +166,32 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
} }
} }
grpc_error *grpc_call_stack_init( grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, grpc_channel_stack *channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, int initial_refs, grpc_iomgr_cb_func destroy,
grpc_call_context_element *context, const void *transport_server_data, void *destroy_arg,
grpc_slice path, gpr_timespec start_time, gpr_timespec deadline, const grpc_call_element_args *elem_args) {
grpc_call_stack *call_stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
size_t count = channel_stack->count; size_t count = channel_stack->count;
grpc_call_element *call_elems; grpc_call_element *call_elems;
char *user_data; char *user_data;
size_t i; size_t i;
call_stack->count = count; elem_args->call_stack->count = count;
GRPC_STREAM_REF_INIT(&call_stack->refcount, initial_refs, destroy, GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy,
destroy_arg, "CALL_STACK"); destroy_arg, "CALL_STACK");
call_elems = CALL_ELEMS_FROM_STACK(call_stack); call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack);
user_data = ((char *)call_elems) + user_data = ((char *)call_elems) +
ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
/* init per-filter data */ /* init per-filter data */
grpc_error *first_error = GRPC_ERROR_NONE; grpc_error *first_error = GRPC_ERROR_NONE;
const grpc_call_element_args args = {
.start_time = start_time,
.call_stack = call_stack,
.server_transport_data = transport_server_data,
.context = context,
.path = path,
.deadline = deadline,
};
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
call_elems[i].filter = channel_elems[i].filter; call_elems[i].filter = channel_elems[i].filter;
call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data; call_elems[i].call_data = user_data;
grpc_error *error = grpc_error *error = call_elems[i].filter->init_call_elem(
call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args); exec_ctx, &call_elems[i], elem_args);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
if (first_error == GRPC_ERROR_NONE) { if (first_error == GRPC_ERROR_NONE) {
first_error = error; first_error = error;
@ -241,15 +232,16 @@ void grpc_call_stack_ignore_set_pollset_or_pollset_set(
void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *then_schedule_closure) {
grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack); grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
size_t count = stack->count; size_t count = stack->count;
size_t i; size_t i;
/* destroy per-filter data */ /* destroy per-filter data */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
elems[i].filter->destroy_call_elem(exec_ctx, &elems[i], final_info, elems[i].filter->destroy_call_elem(
i == count - 1 ? and_free_memory : NULL); exec_ctx, &elems[i], final_info,
i == count - 1 ? then_schedule_closure : NULL);
} }
} }

@ -56,6 +56,7 @@
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/support/arena.h"
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -84,6 +85,7 @@ typedef struct {
grpc_slice path; grpc_slice path;
gpr_timespec start_time; gpr_timespec start_time;
gpr_timespec deadline; gpr_timespec deadline;
gpr_arena *arena;
} grpc_call_element_args; } grpc_call_element_args;
typedef struct { typedef struct {
@ -139,12 +141,12 @@ typedef struct {
/* Destroy per call data. /* Destroy per call data.
The filter does not need to do any chaining. The filter does not need to do any chaining.
The bottom filter of a stack will be passed a non-NULL pointer to The bottom filter of a stack will be passed a non-NULL pointer to
\a and_free_memory that should be passed to gpr_free when destruction \a then_schedule_closure that should be passed to grpc_closure_sched when
is complete. \a final_info contains data about the completed call, mainly destruction is complete. \a final_info contains data about the completed
for reporting purposes. */ call, mainly for reporting purposes. */
void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory); grpc_closure *then_schedule_closure);
/* sizeof(per channel data) */ /* sizeof(per channel data) */
size_t sizeof_channel_data; size_t sizeof_channel_data;
@ -236,12 +238,11 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
/* Initialize a call stack given a channel stack. transport_server_data is /* Initialize a call stack given a channel stack. transport_server_data is
expected to be NULL on a client, or an opaque transport owned pointer on the expected to be NULL on a client, or an opaque transport owned pointer on the
server. */ server. */
grpc_error *grpc_call_stack_init( grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, grpc_channel_stack *channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, int initial_refs, grpc_iomgr_cb_func destroy,
grpc_call_context_element *context, const void *transport_server_data, void *destroy_arg,
grpc_slice path, gpr_timespec start_time, gpr_timespec deadline, const grpc_call_element_args *elem_args);
grpc_call_stack *call_stack);
/* Set a pollset or a pollset_set for a call stack: must occur before the first /* Set a pollset or a pollset_set for a call stack: must occur before the first
* op is started */ * op is started */
void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
@ -271,7 +272,7 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
/* Destroy a call stack */ /* Destroy a call stack */
void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory); grpc_closure *then_schedule_closure);
/* Ignore set pollset{_set} - used by filters if they don't care about pollsets /* Ignore set pollset{_set} - used by filters if they don't care about pollsets
* at all. Does nothing. */ * at all. Does nothing. */

@ -292,7 +292,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices);

@ -88,7 +88,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
int r = grpc_transport_init_stream( int r = grpc_transport_init_stream(
exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
&args->call_stack->refcount, args->server_transport_data); &args->call_stack->refcount, args->server_transport_data, args->arena);
return r == 0 ? GRPC_ERROR_NONE return r == 0 ? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE("transport stream initialization failed"); : GRPC_ERROR_CREATE("transport stream initialization failed");
} }
@ -105,12 +105,12 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *then_schedule_closure) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_transport_destroy_stream(exec_ctx, chand->transport, grpc_transport_destroy_stream(exec_ctx, chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld), TRANSPORT_STREAM_FROM_CALL_DATA(calld),
and_free_memory); then_schedule_closure);
} }
/* Constructor for channel_data */ /* Constructor for channel_data */

@ -256,7 +256,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
// Destructor for call_data. Used for both client and server filters. // Destructor for call_data. Used for both client and server filters.
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
void* and_free_memory) { grpc_closure* ignored) {
grpc_deadline_state_destroy(exec_ctx, elem); grpc_deadline_state_destroy(exec_ctx, elem);
} }

@ -412,7 +412,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices);
} }

@ -358,7 +358,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_slice_buffer_destroy_internal(exec_ctx, &calld->read_slice_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &calld->read_slice_buffer);
} }

@ -200,7 +200,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
// Destructor for call_data. // Destructor for call_data.
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
void* ignored) {} grpc_closure* ignored) {}
// Constructor for channel_data. // Constructor for channel_data.
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,

@ -318,7 +318,7 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_call_credentials_unref(exec_ctx, calld->creds); grpc_call_credentials_unref(exec_ctx, calld->creds);
if (calld->have_host) { if (calld->have_host) {

@ -227,7 +227,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) {} grpc_closure *ignored) {}
/* Constructor for channel_data */ /* Constructor for channel_data */
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,

@ -0,0 +1,98 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/support/arena.h"
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
(((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
typedef struct zone {
size_t size_begin;
size_t size_end;
gpr_atm next_atm;
} zone;
struct gpr_arena {
gpr_atm size_so_far;
zone initial_zone;
};
gpr_arena *gpr_arena_create(size_t initial_size) {
initial_size = ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
gpr_arena *a = gpr_zalloc(sizeof(gpr_arena) + initial_size);
a->initial_zone.size_end = initial_size;
return a;
}
size_t gpr_arena_destroy(gpr_arena *arena) {
gpr_atm size = gpr_atm_no_barrier_load(&arena->size_so_far);
zone *z = (zone *)gpr_atm_no_barrier_load(&arena->initial_zone.next_atm);
gpr_free(arena);
while (z) {
zone *next_z = (zone *)gpr_atm_no_barrier_load(&z->next_atm);
gpr_free(z);
z = next_z;
}
return (size_t)size;
}
void *gpr_arena_alloc(gpr_arena *arena, size_t size) {
size = ROUND_UP_TO_ALIGNMENT_SIZE(size);
size_t start =
(size_t)gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size);
zone *z = &arena->initial_zone;
while (start > z->size_end) {
zone *next_z = (zone *)gpr_atm_acq_load(&z->next_atm);
if (next_z == NULL) {
size_t next_z_size = (size_t)gpr_atm_no_barrier_load(&arena->size_so_far);
next_z = gpr_zalloc(sizeof(zone) + next_z_size);
next_z->size_begin = z->size_end;
next_z->size_end = z->size_end + next_z_size;
if (!gpr_atm_rel_cas(&z->next_atm, (gpr_atm)NULL, (gpr_atm)next_z)) {
gpr_free(next_z);
next_z = (zone *)gpr_atm_acq_load(&z->next_atm);
}
}
z = next_z;
}
if (start + size > z->size_end) {
return gpr_arena_alloc(arena, size);
}
GPR_ASSERT(start >= z->size_begin);
GPR_ASSERT(start + size <= z->size_end);
return ((char *)(z + 1)) + start - z->size_begin;
}

@ -0,0 +1,54 @@
/*
*
* 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.
*
*/
// \file Arena based allocator
// Allows very fast allocation of memory, but that memory cannot be freed until
// the arena as a whole is freed
// Tracks the total memory allocated against it, so that future arenas can
// pre-allocate the right amount of memory
#ifndef GRPC_CORE_LIB_SUPPORT_ARENA_H
#define GRPC_CORE_LIB_SUPPORT_ARENA_H
#include <stddef.h>
typedef struct gpr_arena gpr_arena;
// Create an arena, with \a initial_size bytes in the first allocated buffer
gpr_arena *gpr_arena_create(size_t initial_size);
// Allocate \a size bytes from the arena
void *gpr_arena_alloc(gpr_arena *arena, size_t size);
// Destroy an arena, returning the total number of bytes allocated
size_t gpr_arena_destroy(gpr_arena *arena);
#endif /* GRPC_CORE_LIB_SUPPORT_ARENA_H */

@ -51,6 +51,7 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/arena.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/call.h"
@ -138,14 +139,15 @@ typedef struct batch_control {
} batch_control; } batch_control;
struct grpc_call { struct grpc_call {
gpr_arena *arena;
grpc_completion_queue *cq; grpc_completion_queue *cq;
grpc_polling_entity pollent; grpc_polling_entity pollent;
grpc_channel *channel; grpc_channel *channel;
grpc_call *parent; grpc_call *parent;
grpc_call *first_child; grpc_call *first_child;
gpr_timespec start_time; gpr_timespec start_time;
/* TODO(ctiller): share with cq if possible? */ /* protects first_child, and child next/prev links */
gpr_mu mu; gpr_mu child_list_mu;
/* client or server call */ /* client or server call */
bool is_client; bool is_client;
@ -160,8 +162,8 @@ struct grpc_call {
bool received_initial_metadata; bool received_initial_metadata;
bool receiving_message; bool receiving_message;
bool requested_final_op; bool requested_final_op;
bool received_final_op; gpr_atm any_ops_sent_atm;
bool sent_any_op; gpr_atm received_final_op_atm;
/* have we received initial metadata */ /* have we received initial metadata */
bool has_initial_md_been_received; bool has_initial_md_been_received;
@ -212,6 +214,8 @@ struct grpc_call {
grpc_closure receiving_initial_metadata_ready; grpc_closure receiving_initial_metadata_ready;
uint32_t test_only_last_message_flags; uint32_t test_only_last_message_flags;
grpc_closure release_call;
union { union {
struct { struct {
grpc_status_code *status; grpc_status_code *status;
@ -273,9 +277,13 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
grpc_channel_get_channel_stack(args->channel); grpc_channel_get_channel_stack(args->channel);
grpc_call *call; grpc_call *call;
GPR_TIMER_BEGIN("grpc_call_create", 0); GPR_TIMER_BEGIN("grpc_call_create", 0);
call = gpr_zalloc(sizeof(grpc_call) + channel_stack->call_stack_size); gpr_arena *arena =
gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel));
call = gpr_arena_alloc(arena,
sizeof(grpc_call) + channel_stack->call_stack_size);
call->arena = arena;
*out_call = call; *out_call = call;
gpr_mu_init(&call->mu); gpr_mu_init(&call->child_list_mu);
call->channel = args->channel; call->channel = args->channel;
call->cq = args->cq; call->cq = args->cq;
call->parent = args->parent_call; call->parent = args->parent_call;
@ -313,7 +321,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(call->is_client); GPR_ASSERT(call->is_client);
GPR_ASSERT(!args->parent_call->is_client); GPR_ASSERT(!args->parent_call->is_client);
gpr_mu_lock(&args->parent_call->mu); gpr_mu_lock(&args->parent_call->child_list_mu);
if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) { if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) {
send_deadline = gpr_time_min( send_deadline = gpr_time_min(
@ -341,6 +349,10 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
} }
if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) { if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
call->cancellation_is_inherited = 1; call->cancellation_is_inherited = 1;
if (gpr_atm_acq_load(&args->parent_call->received_final_op_atm)) {
cancel_with_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
GRPC_ERROR_CANCELLED);
}
} }
if (args->parent_call->first_child == NULL) { if (args->parent_call->first_child == NULL) {
@ -353,18 +365,23 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
call; call;
} }
gpr_mu_unlock(&args->parent_call->mu); gpr_mu_unlock(&args->parent_call->child_list_mu);
} }
call->send_deadline = send_deadline; call->send_deadline = send_deadline;
GRPC_CHANNEL_INTERNAL_REF(args->channel, "call"); GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
/* initial refcount dropped by grpc_call_destroy */ /* initial refcount dropped by grpc_call_destroy */
grpc_call_element_args call_args = {
.call_stack = CALL_STACK_FROM_CALL(call),
.server_transport_data = args->server_transport_data,
.context = call->context,
.path = path,
.start_time = call->start_time,
.deadline = send_deadline,
.arena = call->arena};
add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1, add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1,
destroy_call, call, call->context, destroy_call, call, &call_args));
args->server_transport_data, path,
call->start_time, send_deadline,
CALL_STACK_FROM_CALL(call)));
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE, cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
@ -421,6 +438,14 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON); GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
} }
static void release_call(grpc_exec_ctx *exec_ctx, void *call,
grpc_error *error) {
grpc_call *c = call;
grpc_channel *channel = c->channel;
grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena));
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
}
static void set_status_value_directly(grpc_status_code status, void *dest); static void set_status_value_directly(grpc_status_code status, void *dest);
static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
grpc_error *error) { grpc_error *error) {
@ -435,7 +460,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
if (c->receiving_stream != NULL) { if (c->receiving_stream != NULL) {
grpc_byte_stream_destroy(exec_ctx, c->receiving_stream); grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
} }
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->child_list_mu);
for (ii = 0; ii < c->send_extra_metadata_count; ii++) { for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md); GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md);
} }
@ -447,7 +472,6 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
if (c->cq) { if (c->cq) {
GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
} }
grpc_channel *channel = c->channel;
get_final_status(call, set_status_value_directly, &c->final_info.final_status, get_final_status(call, set_status_value_directly, &c->final_info.final_status,
NULL); NULL);
@ -456,11 +480,12 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
GRPC_ERROR_UNREF( GRPC_ERROR_UNREF(
unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error); unpack_received_status(gpr_atm_acq_load(&c->status[i])).error);
} }
grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c); grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info,
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call"); grpc_closure_init(&c->release_call, release_call, c,
grpc_schedule_on_exec_ctx));
GPR_TIMER_END("destroy_call", 0); GPR_TIMER_END("destroy_call", 0);
} }
@ -473,7 +498,7 @@ void grpc_call_destroy(grpc_call *c) {
GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c)); GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
if (parent) { if (parent) {
gpr_mu_lock(&parent->mu); gpr_mu_lock(&parent->child_list_mu);
if (c == parent->first_child) { if (c == parent->first_child) {
parent->first_child = c->sibling_next; parent->first_child = c->sibling_next;
if (c == parent->first_child) { if (c == parent->first_child) {
@ -482,15 +507,14 @@ void grpc_call_destroy(grpc_call *c) {
c->sibling_prev->sibling_next = c->sibling_next; c->sibling_prev->sibling_next = c->sibling_next;
c->sibling_next->sibling_prev = c->sibling_prev; c->sibling_next->sibling_prev = c->sibling_prev;
} }
gpr_mu_unlock(&parent->mu); gpr_mu_unlock(&parent->child_list_mu);
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child"); GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
} }
gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->destroy_called); GPR_ASSERT(!c->destroy_called);
c->destroy_called = 1; c->destroy_called = 1;
cancel = c->sent_any_op && !c->received_final_op; cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) &&
gpr_mu_unlock(&c->mu); !gpr_atm_acq_load(&c->received_final_op_atm);
if (cancel) { if (cancel) {
cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
GRPC_ERROR_CANCELLED); GRPC_ERROR_CANCELLED);
@ -555,53 +579,25 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
"c=%p, status=%d, description=%s, reserved=%p)", "c=%p, status=%d, description=%s, reserved=%p)",
4, (c, (int)status, description, reserved)); 4, (c, (int)status, description, reserved));
GPR_ASSERT(reserved == NULL); GPR_ASSERT(reserved == NULL);
gpr_mu_lock(&c->mu);
cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status, cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status,
description); description);
gpr_mu_unlock(&c->mu);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
typedef struct termination_closure { static void done_termination(grpc_exec_ctx *exec_ctx, void *call,
grpc_closure closure;
grpc_call *call;
grpc_transport_stream_op op;
} termination_closure;
static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp,
grpc_error *error) { grpc_error *error) {
termination_closure *tc = tcp; GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "termination");
GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "termination");
gpr_free(tc);
}
static void send_termination(grpc_exec_ctx *exec_ctx, void *tcp,
grpc_error *error) {
termination_closure *tc = tcp;
memset(&tc->op, 0, sizeof(tc->op));
tc->op.cancel_error = GRPC_ERROR_REF(error);
/* reuse closure to catch completion */
tc->op.on_complete = grpc_closure_init(&tc->closure, done_termination, tc,
grpc_schedule_on_exec_ctx);
execute_op(exec_ctx, tc->call, &tc->op);
}
static void terminate_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
grpc_error *error) {
termination_closure *tc = gpr_malloc(sizeof(*tc));
memset(tc, 0, sizeof(*tc));
tc->call = c;
GRPC_CALL_INTERNAL_REF(tc->call, "termination");
grpc_closure_sched(exec_ctx, grpc_closure_init(&tc->closure, send_termination,
tc, grpc_schedule_on_exec_ctx),
error);
} }
static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c, static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
status_source source, grpc_error *error) { status_source source, grpc_error *error) {
GRPC_CALL_INTERNAL_REF(c, "termination");
set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error)); set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error));
terminate_with_error(exec_ctx, c, error); grpc_transport_stream_op *op = grpc_make_transport_stream_op(
grpc_closure_create(done_termination, c, grpc_schedule_on_exec_ctx));
op->cancel_error = error;
execute_op(exec_ctx, c, op);
} }
static grpc_error *error_from_status(grpc_status_code status, static grpc_error *error_from_status(grpc_status_code status,
@ -715,9 +711,7 @@ static void set_incoming_compression_algorithm(
grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm( grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
grpc_call *call) { grpc_call *call) {
grpc_compression_algorithm algorithm; grpc_compression_algorithm algorithm;
gpr_mu_lock(&call->mu);
algorithm = call->incoming_compression_algorithm; algorithm = call->incoming_compression_algorithm;
gpr_mu_unlock(&call->mu);
return algorithm; return algorithm;
} }
@ -729,9 +723,7 @@ static grpc_compression_algorithm compression_algorithm_for_level_locked(
uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) { uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
uint32_t flags; uint32_t flags;
gpr_mu_lock(&call->mu);
flags = call->test_only_last_message_flags; flags = call->test_only_last_message_flags;
gpr_mu_unlock(&call->mu);
return flags; return flags;
} }
@ -785,9 +777,7 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) { uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
uint32_t encodings_accepted_by_peer; uint32_t encodings_accepted_by_peer;
gpr_mu_lock(&call->mu);
encodings_accepted_by_peer = call->encodings_accepted_by_peer; encodings_accepted_by_peer = call->encodings_accepted_by_peer;
gpr_mu_unlock(&call->mu);
return encodings_accepted_by_peer; return encodings_accepted_by_peer;
} }
@ -1056,7 +1046,7 @@ static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
} }
static grpc_error *consolidate_batch_errors(batch_control *bctl) { static grpc_error *consolidate_batch_errors(batch_control *bctl) {
size_t n = (size_t)gpr_atm_no_barrier_load(&bctl->num_errors); size_t n = (size_t)gpr_atm_acq_load(&bctl->num_errors);
if (n == 0) { if (n == 0) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} else if (n == 1) { } else if (n == 1) {
@ -1083,8 +1073,6 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
grpc_call *call = bctl->call; grpc_call *call = bctl->call;
grpc_error *error = consolidate_batch_errors(bctl); grpc_error *error = consolidate_batch_errors(bctl);
gpr_mu_lock(&call->mu);
if (bctl->send_initial_metadata) { if (bctl->send_initial_metadata) {
grpc_metadata_batch_destroy( grpc_metadata_batch_destroy(
exec_ctx, exec_ctx,
@ -1103,20 +1091,23 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
recv_trailing_filter(exec_ctx, call, md); recv_trailing_filter(exec_ctx, call, md);
call->received_final_op = true;
/* propagate cancellation to any interested children */ /* 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; child_call = call->first_child;
if (child_call != NULL) { if (child_call != NULL) {
do { do {
next_child_call = child_call->sibling_next; next_child_call = child_call->sibling_next;
if (child_call->cancellation_is_inherited) { if (child_call->cancellation_is_inherited) {
GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel"); GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
grpc_call_cancel(child_call, NULL); cancel_with_error(exec_ctx, child_call, STATUS_FROM_API_OVERRIDE,
GRPC_ERROR_CANCELLED);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel"); GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
} }
child_call = next_child_call; child_call = next_child_call;
} while (child_call != call->first_child); } while (child_call != call->first_child);
} }
gpr_mu_unlock(&call->child_list_mu);
if (call->is_client) { if (call->is_client) {
get_final_status(call, set_status_value_directly, get_final_status(call, set_status_value_directly,
@ -1130,7 +1121,6 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
error = GRPC_ERROR_NONE; error = GRPC_ERROR_NONE;
} }
gpr_mu_unlock(&call->mu);
if (bctl->is_notify_tag_closure) { if (bctl->is_notify_tag_closure) {
/* unrefs bctl->error */ /* unrefs bctl->error */
@ -1221,7 +1211,6 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
grpc_error *error) { grpc_error *error) {
batch_control *bctl = bctlp; batch_control *bctl = bctlp;
grpc_call *call = bctl->call; grpc_call *call = bctl->call;
gpr_mu_lock(&bctl->call->mu);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
if (call->receiving_stream != NULL) { if (call->receiving_stream != NULL) {
grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
@ -1233,11 +1222,9 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
} }
if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE || if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
call->receiving_stream == NULL) { call->receiving_stream == NULL) {
gpr_mu_unlock(&bctl->call->mu);
process_data_after_md(exec_ctx, bctlp); process_data_after_md(exec_ctx, bctlp);
} else { } else {
call->saved_receiving_stream_ready_bctlp = bctlp; call->saved_receiving_stream_ready_bctlp = bctlp;
gpr_mu_unlock(&bctl->call->mu);
} }
} }
@ -1296,7 +1283,7 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
grpc_error *error, bool has_cancelled) { grpc_error *error, bool has_cancelled) {
if (error == GRPC_ERROR_NONE) return; if (error == GRPC_ERROR_NONE) return;
int idx = (int)gpr_atm_no_barrier_fetch_add(&bctl->num_errors, 1); int idx = (int)gpr_atm_full_fetch_add(&bctl->num_errors, 1);
if (idx == 0 && !has_cancelled) { if (idx == 0 && !has_cancelled) {
cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE, cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
@ -1309,8 +1296,6 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
batch_control *bctl = bctlp; batch_control *bctl = bctlp;
grpc_call *call = bctl->call; grpc_call *call = bctl->call;
gpr_mu_lock(&call->mu);
add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false); add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
grpc_metadata_batch *md = grpc_metadata_batch *md =
@ -1336,11 +1321,9 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
receiving_stream_ready, call->saved_receiving_stream_ready_bctlp, receiving_stream_ready, call->saved_receiving_stream_ready_bctlp,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
call->saved_receiving_stream_ready_bctlp = NULL; call->saved_receiving_stream_ready_bctlp = NULL;
grpc_closure_sched(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error)); grpc_closure_run(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error));
} }
gpr_mu_unlock(&call->mu);
finish_batch_step(exec_ctx, bctl); finish_batch_step(exec_ctx, bctl);
} }
@ -1393,7 +1376,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
bctl->notify_tag = notify_tag; bctl->notify_tag = notify_tag;
bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0); bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
gpr_mu_lock(&call->mu);
grpc_transport_stream_op *stream_op = &bctl->op; grpc_transport_stream_op *stream_op = &bctl->op;
memset(stream_op, 0, sizeof(*stream_op)); memset(stream_op, 0, sizeof(*stream_op));
stream_op->covered_by_poller = true; stream_op->covered_by_poller = true;
@ -1679,8 +1661,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_closure_init(&bctl->finish_batch, finish_batch, bctl, grpc_closure_init(&bctl->finish_batch, finish_batch, bctl,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
stream_op->on_complete = &bctl->finish_batch; stream_op->on_complete = &bctl->finish_batch;
call->sent_any_op = true; gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
gpr_mu_unlock(&call->mu);
execute_op(exec_ctx, call, stream_op); execute_op(exec_ctx, call, stream_op);
@ -1711,7 +1692,6 @@ done_with_error:
if (bctl->recv_final_op) { if (bctl->recv_final_op) {
call->requested_final_op = 0; call->requested_final_op = 0;
} }
gpr_mu_unlock(&call->mu);
goto done; goto done;
} }
@ -1760,10 +1740,8 @@ uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; }
grpc_compression_algorithm grpc_call_compression_for_level( grpc_compression_algorithm grpc_call_compression_for_level(
grpc_call *call, grpc_compression_level level) { grpc_call *call, grpc_compression_level level) {
gpr_mu_lock(&call->mu);
grpc_compression_algorithm algo = grpc_compression_algorithm algo =
compression_algorithm_for_level_locked(call, level); compression_algorithm_for_level_locked(call, level);
gpr_mu_unlock(&call->mu);
return algo; return algo;
} }

@ -68,6 +68,8 @@ struct grpc_channel {
grpc_compression_options compression_options; grpc_compression_options compression_options;
grpc_mdelem default_authority; grpc_mdelem default_authority;
gpr_atm call_size_estimate;
gpr_mu registered_call_mu; gpr_mu registered_call_mu;
registered_call *registered_calls; registered_call *registered_calls;
@ -115,6 +117,10 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
gpr_mu_init(&channel->registered_call_mu); gpr_mu_init(&channel->registered_call_mu);
channel->registered_calls = NULL; channel->registered_calls = NULL;
gpr_atm_no_barrier_store(
&channel->call_size_estimate,
(gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size);
grpc_compression_options_init(&channel->compression_options); grpc_compression_options_init(&channel->compression_options);
for (size_t i = 0; i < args->num_args; i++) { for (size_t i = 0; i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
@ -177,6 +183,32 @@ done:
return channel; return channel;
} }
size_t grpc_channel_get_call_size_estimate(grpc_channel *channel) {
#define ROUND_UP_SIZE 256
return ((size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate) +
ROUND_UP_SIZE) &
~(size_t)(ROUND_UP_SIZE - 1);
}
void grpc_channel_update_call_size_estimate(grpc_channel *channel,
size_t size) {
size_t cur = (size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate);
if (cur < size) {
/* size grew: update estimate */
gpr_atm_no_barrier_cas(&channel->call_size_estimate, (gpr_atm)cur,
(gpr_atm)size);
/* if we lose: never mind, something else will likely update soon enough */
} else if (cur == size) {
/* no change: holding pattern */
} else if (cur > 0) {
/* size shrank: decrease estimate */
gpr_atm_no_barrier_cas(
&channel->call_size_estimate, (gpr_atm)cur,
(gpr_atm)(GPR_MIN(cur - 1, (255 * cur + size) / 256)));
/* if we lose: never mind, something else will likely update soon enough */
}
}
char *grpc_channel_get_target(grpc_channel *channel) { char *grpc_channel_get_target(grpc_channel *channel) {
GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel)); GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
return gpr_strdup(channel->target); return gpr_strdup(channel->target);

@ -66,6 +66,9 @@ grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
grpc_channel *channel, grpc_channel *channel,
int status_code); int status_code);
size_t grpc_channel_get_call_size_estimate(grpc_channel *channel);
void grpc_channel_update_call_size_estimate(grpc_channel *channel, size_t size);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifdef GRPC_STREAM_REFCOUNT_DEBUG
void grpc_channel_internal_ref(grpc_channel *channel, const char *reason); void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);
void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel, void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel,

@ -130,8 +130,8 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *then_schedule_closure) {
gpr_free(and_free_memory); grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
} }
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,

@ -898,7 +898,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;

@ -38,4 +38,4 @@
const char *grpc_version_string(void) { return "3.0.0-dev"; } const char *grpc_version_string(void) { return "3.0.0-dev"; }
const char *grpc_g_stands_for(void) { return "green"; } const char *grpc_g_stands_for(void) { return "gentle"; }

@ -162,9 +162,9 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx,
int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx, int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
grpc_transport *transport, grpc_stream *stream, grpc_transport *transport, grpc_stream *stream,
grpc_stream_refcount *refcount, grpc_stream_refcount *refcount,
const void *server_data) { const void *server_data, gpr_arena *arena) {
return transport->vtable->init_stream(exec_ctx, transport, stream, refcount, return transport->vtable->init_stream(exec_ctx, transport, stream, refcount,
server_data); server_data, arena);
} }
void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx, void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx,
@ -197,9 +197,10 @@ void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport,
void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx, void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
grpc_transport *transport, grpc_transport *transport,
grpc_stream *stream, void *and_free_memory) { grpc_stream *stream,
grpc_closure *then_schedule_closure) {
transport->vtable->destroy_stream(exec_ctx, transport, stream, transport->vtable->destroy_stream(exec_ctx, transport, stream,
and_free_memory); then_schedule_closure);
} }
char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
@ -254,8 +255,9 @@ typedef struct {
static void destroy_made_transport_stream_op(grpc_exec_ctx *exec_ctx, void *arg, static void destroy_made_transport_stream_op(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
made_transport_stream_op *op = arg; made_transport_stream_op *op = arg;
grpc_closure_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error)); grpc_closure *c = op->inner_on_complete;
gpr_free(op); gpr_free(op);
grpc_closure_run(exec_ctx, c, GRPC_ERROR_REF(error));
} }
grpc_transport_stream_op *grpc_make_transport_stream_op( grpc_transport_stream_op *grpc_make_transport_stream_op(

@ -41,6 +41,7 @@
#include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/support/arena.h"
#include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/byte_stream.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
@ -229,7 +230,7 @@ size_t grpc_transport_stream_size(grpc_transport *transport);
int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx, int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
grpc_transport *transport, grpc_stream *stream, grpc_transport *transport, grpc_stream *stream,
grpc_stream_refcount *refcount, grpc_stream_refcount *refcount,
const void *server_data); const void *server_data, gpr_arena *arena);
void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport, void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport,
grpc_stream *stream, grpc_polling_entity *pollent); grpc_stream *stream, grpc_polling_entity *pollent);
@ -246,7 +247,8 @@ void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport,
caller, but any child memory must be cleaned up) */ caller, but any child memory must be cleaned up) */
void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx, void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
grpc_transport *transport, grpc_transport *transport,
grpc_stream *stream, void *and_free_memory); grpc_stream *stream,
grpc_closure *then_schedule_closure);
void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx, void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
grpc_transport_stream_op *op, grpc_transport_stream_op *op,

@ -47,7 +47,7 @@ typedef struct grpc_transport_vtable {
/* implementation of grpc_transport_init_stream */ /* implementation of grpc_transport_init_stream */
int (*init_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self, int (*init_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_stream_refcount *refcount, grpc_stream *stream, grpc_stream_refcount *refcount,
const void *server_data); const void *server_data, gpr_arena *arena);
/* implementation of grpc_transport_set_pollset */ /* implementation of grpc_transport_set_pollset */
void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self, void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
@ -67,7 +67,8 @@ typedef struct grpc_transport_vtable {
/* implementation of grpc_transport_destroy_stream */ /* implementation of grpc_transport_destroy_stream */
void (*destroy_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self, void (*destroy_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, void *and_free_memory); grpc_stream *stream,
grpc_closure *then_schedule_closure);
/* implementation of grpc_transport_destroy */ /* implementation of grpc_transport_destroy */
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_transport *self); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_transport *self);

@ -318,7 +318,8 @@ class ChannelFilter final {
static void DestroyCallElement(grpc_exec_ctx *exec_ctx, static void DestroyCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *then_call_closure) {
GPR_ASSERT(then_call_closure == NULL);
reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType(); reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType();
} }

@ -33,6 +33,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/basic_timers.c',
'src/core/lib/profiling/stap_timers.c', 'src/core/lib/profiling/stap_timers.c',
'src/core/lib/support/alloc.c', 'src/core/lib/support/alloc.c',
'src/core/lib/support/arena.c',
'src/core/lib/support/atm.c', 'src/core/lib/support/atm.c',
'src/core/lib/support/avl.c', 'src/core/lib/support/avl.c',
'src/core/lib/support/backoff.c', 'src/core/lib/support/backoff.c',

@ -33,9 +33,10 @@ import threading
import grpc import grpc
from grpc_health.v1 import health_pb2 from grpc_health.v1 import health_pb2
from grpc_health.v1 import health_pb2_grpc
class HealthServicer(health_pb2.HealthServicer): class HealthServicer(health_pb2_grpc.HealthServicer):
"""Servicer handling RPCs for service statuses.""" """Servicer handling RPCs for service statuses."""
def __init__(self): def __init__(self):

@ -34,6 +34,7 @@ import grpc
from grpc.framework.foundation import logging_pool from grpc.framework.foundation import logging_pool
from grpc_health.v1 import health from grpc_health.v1 import health
from grpc_health.v1 import health_pb2 from grpc_health.v1 import health_pb2
from grpc_health.v1 import health_pb2_grpc
from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_constants
@ -52,11 +53,11 @@ class HealthServicerTest(unittest.TestCase):
server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
self._server = grpc.server(server_pool) self._server = grpc.server(server_pool)
port = self._server.add_insecure_port('[::]:0') port = self._server.add_insecure_port('[::]:0')
health_pb2.add_HealthServicer_to_server(servicer, self._server) health_pb2_grpc.add_HealthServicer_to_server(servicer, self._server)
self._server.start() self._server.start()
channel = grpc.insecure_channel('localhost:%d' % port) channel = grpc.insecure_channel('localhost:%d' % port)
self._stub = health_pb2.HealthStub(channel) self._stub = health_pb2_grpc.HealthStub(channel)
def test_empty_service(self): def test_empty_service(self):
request = health_pb2.HealthCheckRequest() request = health_pb2.HealthCheckRequest()

@ -33,7 +33,7 @@
<%include file="../../go_path.include"/> <%include file="../../go_path.include"/>
<%include file="../../python_deps.include"/> <%include file="../../python_deps.include"/>
RUN pip install twisted h2 RUN pip install twisted h2 hyper
# Define the default command. # Define the default command.
CMD ["bash"] CMD ["bash"]

@ -68,7 +68,7 @@ static void channel_destroy_func(grpc_exec_ctx *exec_ctx,
static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *ignored) { grpc_closure *ignored) {
++*(int *)(elem->channel_data); ++*(int *)(elem->channel_data);
} }
@ -139,10 +139,16 @@ static void test_create_channel_stack(void) {
GPR_ASSERT(*channel_data == 0); GPR_ASSERT(*channel_data == 0);
call_stack = gpr_malloc(channel_stack->call_stack_size); call_stack = gpr_malloc(channel_stack->call_stack_size);
grpc_error *error = const grpc_call_element_args args = {
grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, .call_stack = call_stack,
NULL, NULL, path, gpr_now(GPR_CLOCK_MONOTONIC), .server_transport_data = NULL,
gpr_inf_future(GPR_CLOCK_MONOTONIC), call_stack); .context = NULL,
.path = path,
.start_time = gpr_now(GPR_CLOCK_MONOTONIC),
.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC),
.arena = NULL};
grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1,
free_call, call_stack, &args);
GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(call_stack->count == 1); GPR_ASSERT(call_stack->count == 1);
call_elem = grpc_call_stack_element(call_stack, 0); call_elem = grpc_call_stack_element(call_stack, 0);

@ -213,7 +213,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) {} grpc_closure *ignored) {}
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,

@ -236,7 +236,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) {} grpc_closure *ignored) {}
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,

@ -267,7 +267,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *ignored) {
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
g_client_latency = final_info->stats.latency; g_client_latency = final_info->stats.latency;
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
@ -276,7 +276,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) { grpc_closure *ignored) {
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
g_server_latency = final_info->stats.latency; g_server_latency = final_info->stats.latency;
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);

@ -34,7 +34,7 @@ load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
grpc_fuzzer( grpc_fuzzer(
name = "ssl_server_fuzzer", name = "ssl_server_fuzzer",
srcs = ["ssl_server_fuzzer.c"], srcs = ["ssl_server_fuzzer.c"],
deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"], deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util", "//test/core/end2end:ssl_test_data"],
corpus = "corpus", corpus = "corpus",
copts = ["-std=c99"], copts = ["-std=c99"],
) )

@ -38,6 +38,7 @@
#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/security/transport/security_connector.h"
#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/memory_counters.h" #include "test/core/util/memory_counters.h"
#include "test/core/util/mock_endpoint.h" #include "test/core/util/mock_endpoint.h"
@ -46,10 +47,6 @@ bool squelch = true;
// Turning this on will fail the leak check. // Turning this on will fail the leak check.
bool leak_check = false; bool leak_check = false;
#define SSL_CERT_PATH "src/core/lib/tsi/test_creds/server1.pem"
#define SSL_KEY_PATH "src/core/lib/tsi/test_creds/server1.key"
#define SSL_CA_PATH "src/core/lib/tsi/test_creds/ca.pem"
static void discard_write(grpc_slice slice) {} static void discard_write(grpc_slice slice) {}
static void dont_log(gpr_log_func_args *args) {} static void dont_log(gpr_log_func_args *args) {}
@ -88,12 +85,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Load key pair and establish server SSL credentials. // Load key pair and establish server SSL credentials.
grpc_ssl_pem_key_cert_pair pem_key_cert_pair; grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
grpc_slice ca_slice, cert_slice, key_slice; grpc_slice ca_slice, cert_slice, key_slice;
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", ca_slice = grpc_slice_from_static_string(test_root_cert);
grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); cert_slice = grpc_slice_from_static_string(test_server1_cert);
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", key_slice = grpc_slice_from_static_string(test_server1_key);
grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice);
pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice);
pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice);

@ -0,0 +1,139 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/support/arena.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/useful.h>
#include <inttypes.h>
#include <string.h>
#include "src/core/lib/support/string.h"
#include "test/core/util/test_config.h"
static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); }
static void test(const char *name, size_t init_size, const size_t *allocs,
size_t nallocs) {
gpr_strvec v;
char *s;
gpr_strvec_init(&v);
gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
gpr_strvec_add(&v, s);
for (size_t i = 0; i < nallocs; i++) {
gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]);
gpr_strvec_add(&v, s);
}
gpr_strvec_add(&v, gpr_strdup("}"));
s = gpr_strvec_flatten(&v, NULL);
gpr_strvec_destroy(&v);
gpr_log(GPR_INFO, "%s", s);
gpr_free(s);
gpr_arena *a = gpr_arena_create(init_size);
void **ps = gpr_zalloc(sizeof(*ps) * nallocs);
for (size_t i = 0; i < nallocs; i++) {
ps[i] = gpr_arena_alloc(a, allocs[i]);
// ensure no duplicate results
for (size_t j = 0; j < i; j++) {
GPR_ASSERT(ps[i] != ps[j]);
}
// ensure writable
memset(ps[i], 1, allocs[i]);
}
gpr_arena_destroy(a);
gpr_free(ps);
}
#define TEST(name, init_size, ...) \
static const size_t allocs_##name[] = {__VA_ARGS__}; \
test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name))
#define CONCURRENT_TEST_ITERATIONS 100000
#define CONCURRENT_TEST_THREADS 100
typedef struct {
gpr_event ev_start;
gpr_arena *arena;
} concurrent_test_args;
static void concurrent_test_body(void *arg) {
concurrent_test_args *a = arg;
gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME));
for (size_t i = 0; i < CONCURRENT_TEST_ITERATIONS; i++) {
*(char *)gpr_arena_alloc(a->arena, 1) = (char)i;
}
}
static void concurrent_test(void) {
gpr_log(GPR_DEBUG, "concurrent_test");
concurrent_test_args args;
gpr_event_init(&args.ev_start);
args.arena = gpr_arena_create(1024);
gpr_thd_id thds[CONCURRENT_TEST_THREADS];
for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
gpr_thd_options opt = gpr_thd_options_default();
gpr_thd_options_set_joinable(&opt);
gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt);
}
gpr_event_set(&args.ev_start, (void *)1);
for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
gpr_thd_join(thds[i]);
}
gpr_arena_destroy(args.arena);
}
int main(int argc, char *argv[]) {
grpc_test_init(argc, argv);
test_noop();
TEST(0_1, 0, 1);
TEST(1_1, 1, 1);
TEST(1_2, 1, 2);
TEST(1_3, 1, 3);
TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
TEST(6_123, 6, 1, 2, 3);
concurrent_test();
return 0;
}

@ -41,7 +41,7 @@
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/byte_stream.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/http2_client.h" #include "test/cpp/interop/http2_client.h"

@ -38,7 +38,7 @@
#include <grpc++/channel.h> #include <grpc++/channel.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
namespace grpc { namespace grpc {

@ -46,8 +46,8 @@
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/byte_stream.h"
#include "src/proto/grpc/testing/empty.grpc.pb.h" #include "src/proto/grpc/testing/empty.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/client_helper.h" #include "test/cpp/interop/client_helper.h"
#include "test/cpp/interop/interop_client.h" #include "test/cpp/interop/interop_client.h"

@ -38,7 +38,7 @@
#include <grpc++/channel.h> #include <grpc++/channel.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
namespace grpc { namespace grpc {

@ -48,8 +48,8 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/byte_stream.h"
#include "src/proto/grpc/testing/empty.grpc.pb.h" #include "src/proto/grpc/testing/empty.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/server_helper.h" #include "test/cpp/interop/server_helper.h"
#include "test/cpp/util/test_config.h" #include "test/cpp/util/test_config.h"

@ -40,8 +40,8 @@
#include <grpc++/support/channel_arguments.h> #include <grpc++/support/channel_arguments.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/proto/grpc/testing/empty.grpc.pb.h" #include "src/proto/grpc/testing/empty.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/util/create_test_channel.h" #include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/test_config.h" #include "test/cpp/util/test_config.h"

@ -47,8 +47,8 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/proto/grpc/testing/empty.grpc.pb.h" #include "src/proto/grpc/testing/empty.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/core/util/reconnect_server.h" #include "test/core/util/reconnect_server.h"
#include "test/cpp/util/test_config.h" #include "test/cpp/util/test_config.h"

@ -0,0 +1,76 @@
/*
*
* 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.
*
*/
/* Benchmark arenas */
extern "C" {
#include "src/core/lib/support/arena.h"
}
#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
static void BM_Arena_NoOp(benchmark::State& state) {
while (state.KeepRunning()) {
gpr_arena_destroy(gpr_arena_create(state.range(0)));
}
}
BENCHMARK(BM_Arena_NoOp)->Range(1, 1024 * 1024);
static void BM_Arena_ManyAlloc(benchmark::State& state) {
gpr_arena* a = gpr_arena_create(state.range(0));
const size_t realloc_after =
1024 * 1024 * 1024 / ((state.range(1) + 15) & 0xffffff0u);
while (state.KeepRunning()) {
gpr_arena_alloc(a, state.range(1));
// periodically recreate arena to avoid OOM
if (state.iterations() % realloc_after == 0) {
gpr_arena_destroy(a);
a = gpr_arena_create(state.range(0));
}
}
gpr_arena_destroy(a);
}
BENCHMARK(BM_Arena_ManyAlloc)->Ranges({{1, 1024 * 1024}, {1, 32 * 1024}});
static void BM_Arena_Batch(benchmark::State& state) {
while (state.KeepRunning()) {
gpr_arena* a = gpr_arena_create(state.range(0));
for (int i = 0; i < state.range(1); i++) {
gpr_arena_alloc(a, state.range(2));
}
gpr_arena_destroy(a);
}
}
BENCHMARK(BM_Arena_Batch)->Ranges({{1, 64 * 1024}, {1, 64}, {1, 1024}});
BENCHMARK_MAIN();

@ -232,7 +232,7 @@ static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
void *and_free_memory) {} grpc_closure *then_sched_closure) {}
grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
@ -275,7 +275,7 @@ const char *name;
/* implementation of grpc_transport_init_stream */ /* implementation of grpc_transport_init_stream */
int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self, int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_stream_refcount *refcount, grpc_stream *stream, grpc_stream_refcount *refcount,
const void *server_data) { const void *server_data, gpr_arena *arena) {
return 0; return 0;
} }
@ -299,7 +299,7 @@ void PerformOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
/* implementation of grpc_transport_destroy_stream */ /* implementation of grpc_transport_destroy_stream */
void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self, void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, void *and_free_memory) {} grpc_stream *stream, grpc_closure *then_sched_closure) {}
/* implementation of grpc_transport_destroy */ /* implementation of grpc_transport_destroy */
void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {} void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
@ -394,7 +394,7 @@ static void BM_IsolatedFilter(benchmark::State &state) {
grpc_channel_stack *channel_stack = grpc_channel_stack *channel_stack =
static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size)); static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size));
GPR_ASSERT(GRPC_LOG_IF_ERROR( GPR_ASSERT(GRPC_LOG_IF_ERROR(
"call_stack_init", "channel_stack_init",
grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack, grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack,
&filters[0], filters.size(), &channel_args, &filters[0], filters.size(), &channel_args,
fixture.flags & REQUIRES_TRANSPORT fixture.flags & REQUIRES_TRANSPORT
@ -409,15 +409,29 @@ static void BM_IsolatedFilter(benchmark::State &state) {
grpc_slice method = grpc_slice_from_static_string("/foo/bar"); grpc_slice method = grpc_slice_from_static_string("/foo/bar");
grpc_call_final_info final_info; grpc_call_final_info final_info;
TestOp test_op_data; TestOp test_op_data;
grpc_call_element_args call_args;
call_args.call_stack = call_stack;
call_args.server_transport_data = NULL;
call_args.context = NULL;
call_args.path = method;
call_args.start_time = start_time;
call_args.deadline = deadline;
const int kArenaSize = 4096;
call_args.arena = gpr_arena_create(kArenaSize);
while (state.KeepRunning()) { while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1, GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1,
DoNothing, NULL, NULL, NULL, method, DoNothing, NULL, &call_args));
start_time, deadline, call_stack));
typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack); typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack);
grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL); grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL);
op.Finish(&exec_ctx); op.Finish(&exec_ctx);
grpc_exec_ctx_flush(&exec_ctx); grpc_exec_ctx_flush(&exec_ctx);
// recreate arena every 64k iterations to avoid oom
if (0 == (state.iterations() & 0xffff)) {
gpr_arena_destroy(call_args.arena);
call_args.arena = gpr_arena_create(kArenaSize);
}
} }
gpr_arena_destroy(call_args.arena);
grpc_channel_stack_destroy(&exec_ctx, channel_stack); grpc_channel_stack_destroy(&exec_ctx, channel_stack);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
gpr_free(channel_stack); gpr_free(channel_stack);

@ -54,86 +54,144 @@ auto& force_library_initialization = Library::get();
static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); } static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
template <class Fixture> // Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
static void BM_PumpStreamClientToServer(benchmark::State& state) { // messages in each call) in a loop on a single channel
//
// First parmeter (i.e state.range(0)): Message size (in bytes) to use
// Second parameter (i.e state.range(1)): Number of ping pong messages.
// Note: One ping-pong means two messages (one from client to server and
// the other from server to client):
template <class Fixture, class ClientContextMutator, class ServerContextMutator>
static void BM_StreamingPingPong(benchmark::State& state) {
TrackCounters track_counters;
const int msg_size = state.range(0);
const int max_ping_pongs = state.range(1);
EchoTestService::AsyncService service; EchoTestService::AsyncService service;
std::unique_ptr<Fixture> fixture(new Fixture(&service)); std::unique_ptr<Fixture> fixture(new Fixture(&service));
{ {
EchoResponse send_response;
EchoResponse recv_response;
EchoRequest send_request; EchoRequest send_request;
EchoRequest recv_request; EchoRequest recv_request;
if (state.range(0) > 0) {
send_request.set_message(std::string(state.range(0), 'a')); if (msg_size > 0) {
send_request.set_message(std::string(msg_size, 'a'));
send_response.set_message(std::string(msg_size, 'b'));
} }
Status recv_status;
ServerContext svr_ctx;
ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
fixture->cq(), tag(0));
std::unique_ptr<EchoTestService::Stub> stub( std::unique_ptr<EchoTestService::Stub> stub(
EchoTestService::NewStub(fixture->channel())); EchoTestService::NewStub(fixture->channel()));
ClientContext cli_ctx;
auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
int need_tags = (1 << 0) | (1 << 1);
void* t;
bool ok;
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
GPR_ASSERT(ok);
int i = (int)(intptr_t)t;
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i);
}
response_rw.Read(&recv_request, tag(0));
while (state.KeepRunning()) { while (state.KeepRunning()) {
GPR_TIMER_SCOPE("BenchmarkCycle", 0); ServerContext svr_ctx;
request_rw->Write(send_request, tag(1)); ServerContextMutator svr_ctx_mut(&svr_ctx);
while (true) { ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
fixture->cq(), tag(0));
ClientContext cli_ctx;
ClientContextMutator cli_ctx_mut(&cli_ctx);
auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
// Establish async stream between client side and server side
void* t;
bool ok;
int need_tags = (1 << 0) | (1 << 1);
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok)); GPR_ASSERT(fixture->cq()->Next(&t, &ok));
if (t == tag(0)) { GPR_ASSERT(ok);
response_rw.Read(&recv_request, tag(0)); int i = (int)(intptr_t)t;
} else if (t == tag(1)) { GPR_ASSERT(need_tags & (1 << i));
break; need_tags &= ~(1 << i);
} else { }
GPR_ASSERT(false);
// Send 'max_ping_pongs' number of ping pong messages
int ping_pong_cnt = 0;
while (ping_pong_cnt < max_ping_pongs) {
request_rw->Write(send_request, tag(0)); // Start client send
response_rw.Read(&recv_request, tag(1)); // Start server recv
request_rw->Read(&recv_response, tag(2)); // Start client recv
need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
GPR_ASSERT(ok);
int i = (int)(intptr_t)t;
// If server recv is complete, start the server send operation
if (i == 1) {
response_rw.Write(send_response, tag(3));
}
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i);
} }
ping_pong_cnt++;
} }
}
request_rw->WritesDone(tag(1)); request_rw->WritesDone(tag(0));
need_tags = (1 << 0) | (1 << 1); response_rw.Finish(Status::OK, tag(1));
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok)); Status recv_status;
int i = (int)(intptr_t)t; request_rw->Finish(&recv_status, tag(2));
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i); need_tags = (1 << 0) | (1 << 1) | (1 << 2);
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok));
int i = (int)(intptr_t)t;
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i);
}
GPR_ASSERT(recv_status.ok());
} }
} }
fixture->Finish(state); fixture->Finish(state);
fixture.reset(); fixture.reset();
state.SetBytesProcessed(state.range(0) * state.iterations()); state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
track_counters.Finish(state);
} }
template <class Fixture> // Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
static void BM_PumpStreamServerToClient(benchmark::State& state) { // First parmeter (i.e state.range(0)): Message size (in bytes) to use
template <class Fixture, class ClientContextMutator, class ServerContextMutator>
static void BM_StreamingPingPongMsgs(benchmark::State& state) {
TrackCounters track_counters;
const int msg_size = state.range(0);
EchoTestService::AsyncService service; EchoTestService::AsyncService service;
std::unique_ptr<Fixture> fixture(new Fixture(&service)); std::unique_ptr<Fixture> fixture(new Fixture(&service));
{ {
EchoResponse send_response; EchoResponse send_response;
EchoResponse recv_response; EchoResponse recv_response;
if (state.range(0) > 0) { EchoRequest send_request;
send_response.set_message(std::string(state.range(0), 'a')); EchoRequest recv_request;
if (msg_size > 0) {
send_request.set_message(std::string(msg_size, 'a'));
send_response.set_message(std::string(msg_size, 'b'));
} }
Status recv_status;
std::unique_ptr<EchoTestService::Stub> stub(
EchoTestService::NewStub(fixture->channel()));
ServerContext svr_ctx; ServerContext svr_ctx;
ServerContextMutator svr_ctx_mut(&svr_ctx);
ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx); ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(), service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
fixture->cq(), tag(0)); fixture->cq(), tag(0));
std::unique_ptr<EchoTestService::Stub> stub(
EchoTestService::NewStub(fixture->channel()));
ClientContext cli_ctx; ClientContext cli_ctx;
ClientContextMutator cli_ctx_mut(&cli_ctx);
auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1)); auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
int need_tags = (1 << 0) | (1 << 1);
// Establish async stream between client side and server side
void* t; void* t;
bool ok; bool ok;
int need_tags = (1 << 0) | (1 << 1);
while (need_tags) { while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok)); GPR_ASSERT(fixture->cq()->Next(&t, &ok));
GPR_ASSERT(ok); GPR_ASSERT(ok);
@ -141,54 +199,79 @@ static void BM_PumpStreamServerToClient(benchmark::State& state) {
GPR_ASSERT(need_tags & (1 << i)); GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i); need_tags &= ~(1 << i);
} }
request_rw->Read(&recv_response, tag(0));
while (state.KeepRunning()) { while (state.KeepRunning()) {
GPR_TIMER_SCOPE("BenchmarkCycle", 0); GPR_TIMER_SCOPE("BenchmarkCycle", 0);
response_rw.Write(send_response, tag(1)); request_rw->Write(send_request, tag(0)); // Start client send
while (true) { response_rw.Read(&recv_request, tag(1)); // Start server recv
request_rw->Read(&recv_response, tag(2)); // Start client recv
need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok)); GPR_ASSERT(fixture->cq()->Next(&t, &ok));
if (t == tag(0)) { GPR_ASSERT(ok);
request_rw->Read(&recv_response, tag(0)); int i = (int)(intptr_t)t;
} else if (t == tag(1)) {
break; // If server recv is complete, start the server send operation
} else { if (i == 1) {
GPR_ASSERT(false); response_rw.Write(send_response, tag(3));
} }
GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i);
} }
} }
request_rw->WritesDone(tag(0));
response_rw.Finish(Status::OK, tag(1)); response_rw.Finish(Status::OK, tag(1));
need_tags = (1 << 0) | (1 << 1); Status recv_status;
request_rw->Finish(&recv_status, tag(2));
need_tags = (1 << 0) | (1 << 1) | (1 << 2);
while (need_tags) { while (need_tags) {
GPR_ASSERT(fixture->cq()->Next(&t, &ok)); GPR_ASSERT(fixture->cq()->Next(&t, &ok));
int i = (int)(intptr_t)t; int i = (int)(intptr_t)t;
GPR_ASSERT(need_tags & (1 << i)); GPR_ASSERT(need_tags & (1 << i));
need_tags &= ~(1 << i); need_tags &= ~(1 << i);
} }
GPR_ASSERT(recv_status.ok());
} }
fixture->Finish(state); fixture->Finish(state);
fixture.reset(); fixture.reset();
state.SetBytesProcessed(state.range(0) * state.iterations()); state.SetBytesProcessed(msg_size * state.iterations() * 2);
track_counters.Finish(state);
} }
/******************************************************************************* /*******************************************************************************
* CONFIGURATIONS * CONFIGURATIONS
*/ */
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, TCP) // Generate Args for StreamingPingPong benchmarks. Currently generates args for
->Range(0, 128 * 1024 * 1024); // only "small streams" (i.e streams with 0, 1 or 2 messages)
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS) static void StreamingPingPongArgs(benchmark::internal::Benchmark* b) {
->Range(0, 128 * 1024 * 1024); int msg_size = 0;
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, SockPair)
->Range(0, 128 * 1024 * 1024); b->Args({0, 0}); // spl case: 0 ping-pong msgs (msg_size doesn't matter here)
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
->Range(0, 128 * 1024 * 1024); for (msg_size = 0; msg_size <= 128 * 1024 * 1024;
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP) msg_size == 0 ? msg_size++ : msg_size *= 8) {
->Range(0, 128 * 1024 * 1024); b->Args({msg_size, 1});
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS) b->Args({msg_size, 2});
->Range(0, 128 * 1024 * 1024); }
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, SockPair) }
BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
->Apply(StreamingPingPongArgs);
BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
NoOpMutator)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2) BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
->Range(0, 128 * 1024 * 1024); ->Range(0, 128 * 1024 * 1024);
} // namespace testing } // namespace testing

@ -46,7 +46,7 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/proto/grpc/testing/payloads.grpc.pb.h" #include "src/proto/grpc/testing/payloads.pb.h"
#include "src/proto/grpc/testing/services.grpc.pb.h" #include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/cpp/qps/histogram.h" #include "test/cpp/qps/histogram.h"

@ -36,7 +36,7 @@
#include <memory> #include <memory>
#include "src/proto/grpc/testing/control.grpc.pb.h" #include "src/proto/grpc/testing/control.pb.h"
#include "test/cpp/qps/histogram.h" #include "test/cpp/qps/histogram.h"
namespace grpc { namespace grpc {

@ -35,7 +35,7 @@
#define TEST_QPS_HISTOGRAM_H #define TEST_QPS_HISTOGRAM_H
#include <grpc/support/histogram.h> #include <grpc/support/histogram.h>
#include "src/proto/grpc/testing/stats.grpc.pb.h" #include "src/proto/grpc/testing/stats.pb.h"
namespace grpc { namespace grpc {
namespace testing { namespace testing {

@ -38,8 +38,8 @@
#include <grpc/support/cpu.h> #include <grpc/support/cpu.h>
#include <vector> #include <vector>
#include "src/proto/grpc/testing/control.grpc.pb.h" #include "src/proto/grpc/testing/control.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.pb.h"
#include "test/core/end2end/data/ssl_test_data.h" #include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
#include "test/cpp/qps/usage_timer.h" #include "test/cpp/qps/usage_timer.h"

@ -103,24 +103,25 @@ class AsyncQpsServerTest final : public grpc::testing::Server {
server_ = builder.BuildAndStart(); server_ = builder.BuildAndStart();
using namespace std::placeholders;
auto process_rpc_bound = auto process_rpc_bound =
std::bind(process_rpc, config.payload_config(), _1, _2); std::bind(process_rpc, config.payload_config(), std::placeholders::_1,
std::placeholders::_2);
for (int i = 0; i < 15000; i++) { for (int i = 0; i < 15000; i++) {
for (int j = 0; j < num_threads; j++) { for (int j = 0; j < num_threads; j++) {
if (request_unary_function) { if (request_unary_function) {
auto request_unary = auto request_unary = std::bind(
std::bind(request_unary_function, &async_service_, _1, _2, _3, request_unary_function, &async_service_, std::placeholders::_1,
srv_cqs_[j].get(), srv_cqs_[j].get(), _4); std::placeholders::_2, std::placeholders::_3, srv_cqs_[j].get(),
srv_cqs_[j].get(), std::placeholders::_4);
contexts_.emplace_back( contexts_.emplace_back(
new ServerRpcContextUnaryImpl(request_unary, process_rpc_bound)); new ServerRpcContextUnaryImpl(request_unary, process_rpc_bound));
} }
if (request_streaming_function) { if (request_streaming_function) {
auto request_streaming = auto request_streaming = std::bind(
std::bind(request_streaming_function, &async_service_, _1, _2, request_streaming_function, &async_service_,
srv_cqs_[j].get(), srv_cqs_[j].get(), _3); std::placeholders::_1, std::placeholders::_2, srv_cqs_[j].get(),
srv_cqs_[j].get(), std::placeholders::_3);
contexts_.emplace_back(new ServerRpcContextStreamingImpl( contexts_.emplace_back(new ServerRpcContextStreamingImpl(
request_streaming, process_rpc_bound)); request_streaming, process_rpc_bound));
} }

@ -0,0 +1,49 @@
# 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.
import argparse
import hyper
import sys
# Utility to healthcheck the http2 server. Used when starting the server to
# verify that the server is live before tests begin.
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--server_host', type=str, default='localhost')
parser.add_argument('--server_port', type=int, default=8080)
args = parser.parse_args()
server_host = args.server_host
server_port = args.server_port
conn = hyper.HTTP20Connection('%s:%d' % (server_host, server_port))
conn.request('POST', '/grpc.testing.TestService/UnaryCall')
resp = conn.get_response()
if resp.headers.get('grpc-encoding') is None:
sys.exit(1)
else:
sys.exit(0)

@ -31,6 +31,7 @@
import argparse import argparse
import logging import logging
import sys
import twisted import twisted
import twisted.internet import twisted.internet
import twisted.internet.endpoints import twisted.internet.endpoints
@ -53,9 +54,11 @@ _TEST_CASE_MAPPING = {
'max_streams': test_max_streams.TestcaseSettingsMaxStreams, 'max_streams': test_max_streams.TestcaseSettingsMaxStreams,
} }
_exit_code = 0
class H2Factory(twisted.internet.protocol.Factory): class H2Factory(twisted.internet.protocol.Factory):
def __init__(self, testcase): def __init__(self, testcase):
logging.info('Creating H2Factory for new connection.') logging.info('Creating H2Factory for new connection (%s)', testcase)
self._num_streams = 0 self._num_streams = 0
self._testcase = testcase self._testcase = testcase
@ -83,6 +86,17 @@ def parse_arguments():
) )
return parser.parse_args() return parser.parse_args()
def listen(endpoint, test_case):
deferred = endpoint.listen(H2Factory(test_case))
def listen_error(reason):
# If listening fails, we stop the reactor and exit the program
# with exit code 1.
global _exit_code
_exit_code = 1
logging.error('Listening failed: %s' % reason.value)
twisted.internet.reactor.stop()
deferred.addErrback(listen_error)
def start_test_servers(base_port): def start_test_servers(base_port):
""" Start one server per test case on incrementing port numbers """ Start one server per test case on incrementing port numbers
beginning with base_port """ beginning with base_port """
@ -92,7 +106,9 @@ def start_test_servers(base_port):
logging.warning('serving on port %d : %s'%(portnum, test_case)) logging.warning('serving on port %d : %s'%(portnum, test_case))
endpoint = twisted.internet.endpoints.TCP4ServerEndpoint( endpoint = twisted.internet.endpoints.TCP4ServerEndpoint(
twisted.internet.reactor, portnum, backlog=128) twisted.internet.reactor, portnum, backlog=128)
endpoint.listen(H2Factory(test_case)) # Wait until the reactor is running before calling endpoint.listen().
twisted.internet.reactor.callWhenRunning(listen, endpoint, test_case)
index += 1 index += 1
if __name__ == '__main__': if __name__ == '__main__':
@ -102,3 +118,4 @@ if __name__ == '__main__':
args = parse_arguments() args = parse_arguments()
start_test_servers(args.base_port) start_test_servers(args.base_port)
twisted.internet.reactor.run() twisted.internet.reactor.run()
sys.exit(_exit_code)

@ -47,7 +47,7 @@ RUN pip install pip --upgrade
RUN pip install virtualenv RUN pip install virtualenv
RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0
RUN pip install twisted h2 RUN pip install twisted h2 hyper
# Define the default command. # Define the default command.
CMD ["bash"] CMD ["bash"]

@ -1230,6 +1230,8 @@ src/core/lib/slice/slice_internal.h \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/slice/slice_string_helpers.h \ src/core/lib/slice/slice_string_helpers.h \
src/core/lib/support/alloc.c \ src/core/lib/support/alloc.c \
src/core/lib/support/arena.c \
src/core/lib/support/arena.h \
src/core/lib/support/atm.c \ src/core/lib/support/atm.c \
src/core/lib/support/avl.c \ src/core/lib/support/avl.c \
src/core/lib/support/backoff.c \ src/core/lib/support/backoff.c \

@ -0,0 +1,3 @@
[libfuzzer]
max_len = 2048
dict = api_fuzzer.dictionary

@ -0,0 +1,3 @@
[libfuzzer]
max_len = 2048
dict = hpack.dictionary

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 512

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 128

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 128

@ -0,0 +1,3 @@
[libfuzzer]
max_len = 512
dict = hpack.dictionary

@ -0,0 +1,3 @@
[libfuzzer]
max_len = 2048

@ -0,0 +1,3 @@
[libfuzzer]
max_len = 2048

@ -0,0 +1,3 @@
[libfuzzer]
max_len = 2048
dict = hpack.dictionary

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 2048

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 128

@ -0,0 +1,119 @@
#!/usr/bin/env python2.7
# 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.
"""Upload docker images to Google Container Registry."""
from __future__ import print_function
import argparse
import atexit
import os
import shutil
import subprocess
import tempfile
argp = argparse.ArgumentParser(description='Run interop tests.')
argp.add_argument('--gcr_path',
default='gcr.io/grpc-testing',
help='Path of docker images in Google Container Registry')
argp.add_argument('--gcr_tag',
default='latest',
help='the tag string for the images to upload')
argp.add_argument('--with_files',
default=[],
nargs='+',
help='additional files to include in the docker image')
argp.add_argument('--with_file_dest',
default='/var/local/image_info',
help='Destination directory for with_files inside docker image')
argp.add_argument('--images',
default=[],
nargs='+',
help='local docker images in the form of repo:tag ' +
'(i.e. grpc_interop_java:26328ad8) to upload')
argp.add_argument('--keep',
action='store_true',
help='keep the created local images after uploading to GCR')
args = argp.parse_args()
def upload_to_gcr(image):
"""Tags and Pushes a docker image in Google Containger Registry.
image: docker image name, i.e. grpc_interop_java:26328ad8
A docker image image_foo:tag_old will be uploaded as
<gcr_path>/image_foo:<gcr_tag>
after inserting extra with_files under with_file_dest in the image. The
original image name will be stored as label original_name:"image_foo:tag_old".
"""
tag_idx = image.find(':')
if tag_idx == -1:
print('Failed to parse docker image name %s' % image)
return False
new_tag = '%s/%s:%s' % (args.gcr_path, image[:tag_idx], args.gcr_tag)
lines = ['FROM ' + image]
lines.append('LABEL original_name="%s"' % image)
temp_dir = tempfile.mkdtemp()
atexit.register(lambda: subprocess.call(['rm', '-rf', temp_dir]))
# Copy with_files inside the tmp directory, which will be the docker build
# context.
for f in args.with_files:
shutil.copy(f, temp_dir)
lines.append('COPY %s %s/' % (os.path.basename(f), args.with_file_dest))
# Create a Dockerfile.
with open(os.path.join(temp_dir, 'Dockerfile'), 'w') as f:
f.write('\n'.join(lines))
build_cmd = ['docker', 'build', '--rm', '--tag', new_tag, temp_dir]
subprocess.check_output(build_cmd)
if not args.keep:
atexit.register(lambda: subprocess.call(['docker', 'rmi', new_tag]))
# Upload to GCR.
if args.gcr_path:
subprocess.call(['gcloud', 'docker', '--', 'push', new_tag])
return True
for image in args.images:
upload_to_gcr(image)

@ -31,7 +31,7 @@
# Location of the continuous shell script in repository. # Location of the continuous shell script in repository.
build_file: "grpc/tools/internal_ci/linux/grpc_portability.sh" build_file: "grpc/tools/internal_ci/linux/grpc_portability.sh"
timeout_mins: 360 timeout_mins: 720
action { action {
define_artifacts { define_artifacts {
regex: "**/*sponge_log.xml" regex: "**/*sponge_log.xml"

@ -58,7 +58,7 @@
{ {
"config": "ubsan", "config": "ubsan",
"environ": { "environ": {
"UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1" "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt"
} }
}, },
{ {

@ -84,6 +84,21 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "arena_test",
"src": [
"test/core/support/arena_test.c"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",
@ -2429,6 +2444,27 @@
"third_party": false, "third_party": false,
"type": "target" "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_arena",
"src": [
"test/cpp/microbenchmarks/bm_arena.cc"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"benchmark", "benchmark",
@ -7264,6 +7300,7 @@
"include/grpc/support/tls_pthread.h", "include/grpc/support/tls_pthread.h",
"include/grpc/support/useful.h", "include/grpc/support/useful.h",
"src/core/lib/profiling/timers.h", "src/core/lib/profiling/timers.h",
"src/core/lib/support/arena.h",
"src/core/lib/support/backoff.h", "src/core/lib/support/backoff.h",
"src/core/lib/support/block_annotate.h", "src/core/lib/support/block_annotate.h",
"src/core/lib/support/env.h", "src/core/lib/support/env.h",
@ -7311,6 +7348,8 @@
"src/core/lib/profiling/stap_timers.c", "src/core/lib/profiling/stap_timers.c",
"src/core/lib/profiling/timers.h", "src/core/lib/profiling/timers.h",
"src/core/lib/support/alloc.c", "src/core/lib/support/alloc.c",
"src/core/lib/support/arena.c",
"src/core/lib/support/arena.h",
"src/core/lib/support/atm.c", "src/core/lib/support/atm.c",
"src/core/lib/support/avl.c", "src/core/lib/support/avl.c",
"src/core/lib/support/backoff.c", "src/core/lib/support/backoff.c",

@ -89,6 +89,28 @@
"windows" "windows"
] ]
}, },
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "arena_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{ {
"args": [], "args": [],
"ci_platforms": [ "ci_platforms": [
@ -2607,6 +2629,28 @@
"windows" "windows"
] ]
}, },
{
"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_arena",
"platforms": [
"linux",
"mac",
"posix"
]
},
{ {
"args": [ "args": [
"--benchmark_min_time=0" "--benchmark_min_time=0"

@ -70,6 +70,23 @@ def docker_mapped_port(cid, port, timeout_seconds=15):
(port, cid)) (port, cid))
def wait_for_healthy(cid, shortname, timeout_seconds):
"""Wait timeout_seconds for the container to become healthy"""
started = time.time()
while time.time() - started < timeout_seconds:
try:
output = subprocess.check_output(
['docker', 'inspect', '--format="{{.State.Health.Status}}"', cid],
stderr=_DEVNULL)
if output.strip('\n') == 'healthy':
return
except subprocess.CalledProcessError as e:
pass
time.sleep(1)
raise Exception('Timed out waiting for %s (%s) to pass health check' %
(shortname, cid))
def finish_jobs(jobs): def finish_jobs(jobs):
"""Kills given docker containers and waits for corresponding jobs to finish""" """Kills given docker containers and waits for corresponding jobs to finish"""
for job in jobs: for job in jobs:
@ -113,6 +130,9 @@ class DockerJob:
def mapped_port(self, port): def mapped_port(self, port):
return docker_mapped_port(self._container_name, port) return docker_mapped_port(self._container_name, port)
def wait_for_healthy(self, timeout_seconds):
wait_for_healthy(self._container_name, self._spec.shortname, timeout_seconds)
def kill(self, suppress_failure=False): def kill(self, suppress_failure=False):
"""Sends kill signal to the container.""" """Sends kill signal to the container."""
if suppress_failure: if suppress_failure:

@ -634,17 +634,13 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
common_options = [ common_options = [
'--test_case=%s' % test_case, '--test_case=%s' % test_case,
'--server_host=%s' % server_host, '--server_host=%s' % server_host,
'--server_port=%s' % server_port,
] ]
if test_case in _HTTP2_BADSERVER_TEST_CASES: if test_case in _HTTP2_BADSERVER_TEST_CASES:
# We are running the http2_badserver_interop test. Adjust command line accordingly. cmdline = bash_cmdline(language.client_cmd_http2interop(common_options))
offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case)
client_options = common_options + ['--server_port=%s' %
(int(server_port)+offset)]
cmdline = bash_cmdline(language.client_cmd_http2interop(client_options))
cwd = language.http2_cwd cwd = language.http2_cwd
else: else:
client_options = interop_only_options + common_options + ['--server_port=%s' % server_port] cmdline = bash_cmdline(language.client_cmd(common_options+interop_only_options))
cmdline = bash_cmdline(language.client_cmd(client_options))
cwd = language.client_cwd cwd = language.client_cwd
environ = language.global_env() environ = language.global_env()
@ -682,30 +678,40 @@ def server_jobspec(language, docker_image, insecure=False, manual_cmd_log=None):
language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT, language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT,
'--use_tls=%s' % ('false' if insecure else 'true')])) '--use_tls=%s' % ('false' if insecure else 'true')]))
environ = language.global_env() environ = language.global_env()
docker_args = ['--name=%s' % container_name]
if language.safename == 'http2': if language.safename == 'http2':
# we are running the http2 interop server. Open next N ports beginning # we are running the http2 interop server. Open next N ports beginning
# with the server port. These ports are used for http2 interop test # with the server port. These ports are used for http2 interop test
# (one test case per port). We also attach the docker container running # (one test case per port).
# the server to local network, so we don't have to mess with port mapping docker_args += list(
port_args = [ itertools.chain.from_iterable(('-p', str(_DEFAULT_SERVER_PORT + i))
'-p', str(_DEFAULT_SERVER_PORT+0), for i in range(
'-p', str(_DEFAULT_SERVER_PORT+1), len(_HTTP2_BADSERVER_TEST_CASES))))
'-p', str(_DEFAULT_SERVER_PORT+2), # Enable docker's healthcheck mechanism.
'-p', str(_DEFAULT_SERVER_PORT+3), # This runs a Python script inside the container every second. The script
'-p', str(_DEFAULT_SERVER_PORT+4), # pings the http2 server to verify it is ready. The 'health-retries' flag
'-p', str(_DEFAULT_SERVER_PORT+5), # specifies the number of consecutive failures before docker will report
'-p', str(_DEFAULT_SERVER_PORT+6), # the container's status as 'unhealthy'. Prior to the first 'health_retries'
'--net=host', # failures or the first success, the status will be 'starting'. 'docker ps'
# or 'docker inspect' can be used to see the health of the container on the
# command line.
docker_args += [
'--health-cmd=python test/http2_test/http2_server_health_check.py '
'--server_host=%s --server_port=%d'
% ('localhost', _DEFAULT_SERVER_PORT),
'--health-interval=1s',
'--health-retries=5',
'--health-timeout=10s',
] ]
else: else:
port_args = ['-p', str(_DEFAULT_SERVER_PORT)] docker_args += ['-p', str(_DEFAULT_SERVER_PORT)]
docker_cmdline = docker_run_cmdline(cmdline, docker_cmdline = docker_run_cmdline(cmdline,
image=docker_image, image=docker_image,
cwd=language.server_cwd, cwd=language.server_cwd,
environ=environ, environ=environ,
docker_args=port_args + docker_args=docker_args)
['--name=%s' % container_name])
if manual_cmd_log is not None: if manual_cmd_log is not None:
manual_cmd_log.append(manual_cmdline(docker_cmdline)) manual_cmd_log.append(manual_cmdline(docker_cmdline))
server_job = jobset.JobSpec( server_job = jobset.JobSpec(
@ -892,7 +898,8 @@ languages = set(_LANGUAGES[l]
languages_http2_badserver_interop = set() languages_http2_badserver_interop = set()
if args.http2_badserver_interop: if args.http2_badserver_interop:
languages_http2_badserver_interop = set( languages_http2_badserver_interop = set(
_LANGUAGES[l] for l in _LANGUAGES_FOR_HTTP2_BADSERVER_TESTS) _LANGUAGES[l] for l in _LANGUAGES_FOR_HTTP2_BADSERVER_TESTS
if 'all' in args.language or l in args.language)
http2Interop = Http2Client() if args.http2_interop else None http2Interop = Http2Client() if args.http2_interop else None
http2InteropServer = Http2Server() if args.http2_badserver_interop else None http2InteropServer = Http2Server() if args.http2_badserver_interop else None
@ -936,6 +943,7 @@ client_manual_cmd_log = [] if args.manual_run else None
# Start interop servers. # Start interop servers.
server_jobs = {} server_jobs = {}
server_addresses = {} server_addresses = {}
http2_badserver_ports = ()
try: try:
for s in servers: for s in servers:
lang = str(s) lang = str(s)
@ -949,14 +957,15 @@ try:
# don't run the server, set server port to a placeholder value # don't run the server, set server port to a placeholder value
server_addresses[lang] = ('localhost', '${SERVER_PORT}') server_addresses[lang] = ('localhost', '${SERVER_PORT}')
http2_badserver_job = None
if args.http2_badserver_interop: if args.http2_badserver_interop:
# launch a HTTP2 server emulator that creates edge cases # launch a HTTP2 server emulator that creates edge cases
lang = str(http2InteropServer) lang = str(http2InteropServer)
spec = server_jobspec(http2InteropServer, docker_images.get(lang), spec = server_jobspec(http2InteropServer, docker_images.get(lang),
manual_cmd_log=server_manual_cmd_log) manual_cmd_log=server_manual_cmd_log)
if not args.manual_run: if not args.manual_run:
job = dockerjob.DockerJob(spec) http2_badserver_job = dockerjob.DockerJob(spec)
server_jobs[lang] = job server_jobs[lang] = http2_badserver_job
else: else:
# don't run the server, set server port to a placeholder value # don't run the server, set server port to a placeholder value
server_addresses[lang] = ('localhost', '${SERVER_PORT}') server_addresses[lang] = ('localhost', '${SERVER_PORT}')
@ -1041,13 +1050,19 @@ try:
jobs.append(test_job) jobs.append(test_job)
if args.http2_badserver_interop: if args.http2_badserver_interop:
if not args.manual_run:
http2_badserver_job.wait_for_healthy(timeout_seconds=600)
for language in languages_http2_badserver_interop: for language in languages_http2_badserver_interop:
for test_case in _HTTP2_BADSERVER_TEST_CASES: for test_case in _HTTP2_BADSERVER_TEST_CASES:
offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case)
server_port = _DEFAULT_SERVER_PORT+offset
if not args.manual_run:
server_port = http2_badserver_job.mapped_port(server_port)
test_job = cloud_to_cloud_jobspec(language, test_job = cloud_to_cloud_jobspec(language,
test_case, test_case,
str(http2InteropServer), str(http2InteropServer),
'localhost', 'localhost',
_DEFAULT_SERVER_PORT, server_port,
docker_image=docker_images.get(str(language)), docker_image=docker_images.get(str(language)),
manual_cmd_log=client_manual_cmd_log) manual_cmd_log=client_manual_cmd_log)
jobs.append(test_job) jobs.append(test_job)

@ -6,6 +6,8 @@ race:cleanse_ctr
race:ssleay_rand_add race:ssleay_rand_add
race:ssleay_rand_bytes race:ssleay_rand_bytes
race:__sleep_for race:__sleep_for
# protobuf has an idempotent write race in ByteSize # protobuf has an idempotent write race in ByteSize/GetCachedSize
# https://github.com/google/protobuf/issues/2169 # https://github.com/google/protobuf/issues/2169
race:ByteSize race:ByteSize
race:ByteSizeLong
race:GetCachedSize

@ -0,0 +1,7 @@
# boringssl stuff
nonnull-attribute:bn_wexpand
nonnull-attribute:CBB_add_bytes
nonnull-attribute:rsa_blinding_get
nonnull-attribute:ssl_copy_key_material
alignment:CRYPTO_cbc128_encrypt

@ -45,6 +45,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alpn_test", "vcxproj\test\a
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arena_test", "vcxproj\test\arena_test\arena_test.vcxproj", "{D85AC722-A88F-4280-F62E-672F571787FF}"
ProjectSection(myProperties) = preProject
lib = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bad_client_test", "vcxproj\test/bad_client\bad_client_test\bad_client_test.vcxproj", "{BA67B418-B699-E41A-9CC4-0279C49481A5}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bad_client_test", "vcxproj\test/bad_client\bad_client_test\bad_client_test.vcxproj", "{BA67B418-B699-E41A-9CC4-0279C49481A5}"
ProjectSection(myProperties) = preProject ProjectSection(myProperties) = preProject
lib = "True" lib = "True"
@ -1708,6 +1717,22 @@ Global
{5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|Win32.Build.0 = Release|Win32 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|Win32.Build.0 = Release|Win32
{5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.ActiveCfg = Release|x64 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.ActiveCfg = Release|x64
{5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.Build.0 = Release|x64 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.Build.0 = Release|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug|Win32.ActiveCfg = Debug|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug|x64.ActiveCfg = Debug|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Release|Win32.ActiveCfg = Release|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Release|x64.ActiveCfg = Release|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug|Win32.Build.0 = Debug|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug|x64.Build.0 = Debug|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Release|Win32.Build.0 = Release|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Release|x64.Build.0 = Release|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug-DLL|Win32.Build.0 = Debug|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug-DLL|x64.ActiveCfg = Debug|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Debug-DLL|x64.Build.0 = Debug|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Release-DLL|Win32.ActiveCfg = Release|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Release-DLL|Win32.Build.0 = Release|Win32
{D85AC722-A88F-4280-F62E-672F571787FF}.Release-DLL|x64.ActiveCfg = Release|x64
{D85AC722-A88F-4280-F62E-672F571787FF}.Release-DLL|x64.Build.0 = Release|x64
{BA67B418-B699-E41A-9CC4-0279C49481A5}.Debug|Win32.ActiveCfg = Debug|Win32 {BA67B418-B699-E41A-9CC4-0279C49481A5}.Debug|Win32.ActiveCfg = Debug|Win32
{BA67B418-B699-E41A-9CC4-0279C49481A5}.Debug|x64.ActiveCfg = Debug|x64 {BA67B418-B699-E41A-9CC4-0279C49481A5}.Debug|x64.ActiveCfg = Debug|x64
{BA67B418-B699-E41A-9CC4-0279C49481A5}.Release|Win32.ActiveCfg = Release|Win32 {BA67B418-B699-E41A-9CC4-0279C49481A5}.Release|Win32.ActiveCfg = Release|Win32

@ -188,6 +188,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\support\arena.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" />
@ -208,6 +209,8 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\alloc.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\alloc.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\arena.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\atm.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\atm.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\avl.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\avl.c">

@ -10,6 +10,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\alloc.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\alloc.c">
<Filter>src\core\lib\support</Filter> <Filter>src\core\lib\support</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\arena.c">
<Filter>src\core\lib\support</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\atm.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\atm.c">
<Filter>src\core\lib\support</Filter> <Filter>src\core\lib\support</Filter>
</ClCompile> </ClCompile>
@ -257,6 +260,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\profiling\timers.h">
<Filter>src\core\lib\profiling</Filter> <Filter>src\core\lib\profiling</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\support\arena.h">
<Filter>src\core\lib\support</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h">
<Filter>src\core\lib\support</Filter> <Filter>src\core\lib\support</Filter>
</ClInclude> </ClInclude>

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D85AC722-A88F-4280-F62E-672F571787FF}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>arena_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>arena_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\support\arena_test.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\support\arena_test.c">
<Filter>test\core\support</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{130788b2-eacc-90df-a4f6-f5102a7d3370}</UniqueIdentifier>
</Filter>
<Filter Include="test\core">
<UniqueIdentifier>{5c3e1753-6fdb-9476-f98c-a3a394fac54a}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\support">
<UniqueIdentifier>{1d3d2cc8-4e69-8b2e-6ceb-6569fcb19a86}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save