Merge remote-tracking branch 'upstream/master' into feature/qps-bazel-test

pull/16402/head
Bill Feng 7 years ago
commit 06d5c830aa
  1. 4
      BUILD
  2. 76
      CMakeLists.txt
  3. 84
      Makefile
  4. 31
      build.yaml
  5. 2
      config.m4
  6. 2
      config.w32
  7. 4
      gRPC-C++.podspec
  8. 6
      gRPC-Core.podspec
  9. 4
      grpc.gemspec
  10. 8
      grpc.gyp
  11. 4
      package.xml
  12. 2
      src/core/ext/filters/client_channel/http_connect_handshaker.cc
  13. 2
      src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
  14. 2
      src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc
  15. 3
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  16. 2
      src/core/lib/http/httpcli.cc
  17. 134
      src/core/lib/iomgr/buffer_list.cc
  18. 96
      src/core/lib/iomgr/buffer_list.h
  19. 4
      src/core/lib/iomgr/endpoint.cc
  20. 8
      src/core/lib/iomgr/endpoint.h
  21. 2
      src/core/lib/iomgr/endpoint_cfstream.cc
  22. 4
      src/core/lib/iomgr/endpoint_pair_posix.cc
  23. 114
      src/core/lib/iomgr/ev_poll_posix.cc
  24. 9
      src/core/lib/iomgr/ev_posix.cc
  25. 6
      src/core/lib/iomgr/fork_posix.cc
  26. 40
      src/core/lib/iomgr/internal_errqueue.cc
  27. 62
      src/core/lib/iomgr/internal_errqueue.h
  28. 6
      src/core/lib/iomgr/port.h
  29. 2
      src/core/lib/iomgr/tcp_client_posix.cc
  30. 2
      src/core/lib/iomgr/tcp_custom.cc
  31. 311
      src/core/lib/iomgr/tcp_posix.cc
  32. 3
      src/core/lib/iomgr/tcp_posix.h
  33. 4
      src/core/lib/iomgr/tcp_server_posix.cc
  34. 2
      src/core/lib/iomgr/tcp_server_utils_posix_common.cc
  35. 2
      src/core/lib/iomgr/tcp_windows.cc
  36. 2
      src/core/lib/iomgr/udp_server.cc
  37. 4
      src/core/lib/security/transport/secure_endpoint.cc
  38. 2
      src/core/lib/security/transport/security_handshaker.cc
  39. 9
      src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pyx.pxi
  40. 2
      src/python/grpcio/grpc_core_dependencies.py
  41. 2
      test/core/bad_client/bad_client.cc
  42. 13
      test/core/end2end/BUILD
  43. 2
      test/core/end2end/bad_server_response_test.cc
  44. 10
      test/core/end2end/fixtures/http_proxy_fixture.cc
  45. 498
      test/core/end2end/inproc_callback_test.cc
  46. 13
      test/core/iomgr/BUILD
  47. 111
      test/core/iomgr/buffer_list_test.cc
  48. 7
      test/core/iomgr/endpoint_tests.cc
  49. 109
      test/core/iomgr/tcp_posix_test.cc
  50. 2
      test/core/util/mock_endpoint.cc
  51. 2
      test/core/util/passthru_endpoint.cc
  52. 5
      test/core/util/trickle_endpoint.cc
  53. 2
      test/cpp/microbenchmarks/bm_chttp2_transport.cc
  54. 2
      tools/doxygen/Doxyfile.c++.internal
  55. 4
      tools/doxygen/Doxyfile.core.internal
  56. 43
      tools/run_tests/generated/sources_and_headers.json
  57. 44
      tools/run_tests/generated/tests.json

@ -696,6 +696,7 @@ grpc_cc_library(
"src/core/lib/http/format_request.cc", "src/core/lib/http/format_request.cc",
"src/core/lib/http/httpcli.cc", "src/core/lib/http/httpcli.cc",
"src/core/lib/http/parser.cc", "src/core/lib/http/parser.cc",
"src/core/lib/iomgr/buffer_list.cc",
"src/core/lib/iomgr/call_combiner.cc", "src/core/lib/iomgr/call_combiner.cc",
"src/core/lib/iomgr/combiner.cc", "src/core/lib/iomgr/combiner.cc",
"src/core/lib/iomgr/endpoint.cc", "src/core/lib/iomgr/endpoint.cc",
@ -716,6 +717,7 @@ grpc_cc_library(
"src/core/lib/iomgr/gethostname_fallback.cc", "src/core/lib/iomgr/gethostname_fallback.cc",
"src/core/lib/iomgr/gethostname_host_name_max.cc", "src/core/lib/iomgr/gethostname_host_name_max.cc",
"src/core/lib/iomgr/gethostname_sysconf.cc", "src/core/lib/iomgr/gethostname_sysconf.cc",
"src/core/lib/iomgr/internal_errqueue.cc",
"src/core/lib/iomgr/iocp_windows.cc", "src/core/lib/iomgr/iocp_windows.cc",
"src/core/lib/iomgr/iomgr.cc", "src/core/lib/iomgr/iomgr.cc",
"src/core/lib/iomgr/iomgr_custom.cc", "src/core/lib/iomgr/iomgr_custom.cc",
@ -845,6 +847,7 @@ grpc_cc_library(
"src/core/lib/http/format_request.h", "src/core/lib/http/format_request.h",
"src/core/lib/http/httpcli.h", "src/core/lib/http/httpcli.h",
"src/core/lib/http/parser.h", "src/core/lib/http/parser.h",
"src/core/lib/iomgr/buffer_list.h",
"src/core/lib/iomgr/block_annotate.h", "src/core/lib/iomgr/block_annotate.h",
"src/core/lib/iomgr/call_combiner.h", "src/core/lib/iomgr/call_combiner.h",
"src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/closure.h",
@ -862,6 +865,7 @@ grpc_cc_library(
"src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/executor.h",
"src/core/lib/iomgr/gethostname.h", "src/core/lib/iomgr/gethostname.h",
"src/core/lib/iomgr/gevent_util.h", "src/core/lib/iomgr/gevent_util.h",
"src/core/lib/iomgr/internal_errqueue.h",
"src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iocp_windows.h",
"src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_custom.h", "src/core/lib/iomgr/iomgr_custom.h",

@ -230,6 +230,9 @@ add_dependencies(buildtests_c avl_test)
add_dependencies(buildtests_c bad_server_response_test) add_dependencies(buildtests_c bad_server_response_test)
add_dependencies(buildtests_c bin_decoder_test) add_dependencies(buildtests_c bin_decoder_test)
add_dependencies(buildtests_c bin_encoder_test) add_dependencies(buildtests_c bin_encoder_test)
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c buffer_list_test)
endif()
add_dependencies(buildtests_c channel_create_test) add_dependencies(buildtests_c channel_create_test)
add_dependencies(buildtests_c chttp2_hpack_encoder_test) add_dependencies(buildtests_c chttp2_hpack_encoder_test)
add_dependencies(buildtests_c chttp2_stream_map_test) add_dependencies(buildtests_c chttp2_stream_map_test)
@ -331,6 +334,7 @@ if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c httpscli_test) add_dependencies(buildtests_c httpscli_test)
endif() endif()
add_dependencies(buildtests_c init_test) add_dependencies(buildtests_c init_test)
add_dependencies(buildtests_c inproc_callback_test)
add_dependencies(buildtests_c invalid_call_argument_test) add_dependencies(buildtests_c invalid_call_argument_test)
add_dependencies(buildtests_c json_rewrite) add_dependencies(buildtests_c json_rewrite)
add_dependencies(buildtests_c json_rewrite_test) add_dependencies(buildtests_c json_rewrite_test)
@ -958,6 +962,7 @@ add_library(grpc
src/core/lib/http/format_request.cc src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc src/core/lib/http/parser.cc
src/core/lib/iomgr/buffer_list.cc
src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint.cc src/core/lib/iomgr/endpoint.cc
@ -978,6 +983,7 @@ add_library(grpc
src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_fallback.cc
src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_host_name_max.cc
src/core/lib/iomgr/gethostname_sysconf.cc src/core/lib/iomgr/gethostname_sysconf.cc
src/core/lib/iomgr/internal_errqueue.cc
src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iocp_windows.cc
src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_custom.cc src/core/lib/iomgr/iomgr_custom.cc
@ -1364,6 +1370,7 @@ add_library(grpc_cronet
src/core/lib/http/format_request.cc src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc src/core/lib/http/parser.cc
src/core/lib/iomgr/buffer_list.cc
src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint.cc src/core/lib/iomgr/endpoint.cc
@ -1384,6 +1391,7 @@ add_library(grpc_cronet
src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_fallback.cc
src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_host_name_max.cc
src/core/lib/iomgr/gethostname_sysconf.cc src/core/lib/iomgr/gethostname_sysconf.cc
src/core/lib/iomgr/internal_errqueue.cc
src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iocp_windows.cc
src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_custom.cc src/core/lib/iomgr/iomgr_custom.cc
@ -1756,6 +1764,7 @@ add_library(grpc_test_util
src/core/lib/http/format_request.cc src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc src/core/lib/http/parser.cc
src/core/lib/iomgr/buffer_list.cc
src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint.cc src/core/lib/iomgr/endpoint.cc
@ -1776,6 +1785,7 @@ add_library(grpc_test_util
src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_fallback.cc
src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_host_name_max.cc
src/core/lib/iomgr/gethostname_sysconf.cc src/core/lib/iomgr/gethostname_sysconf.cc
src/core/lib/iomgr/internal_errqueue.cc
src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iocp_windows.cc
src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_custom.cc src/core/lib/iomgr/iomgr_custom.cc
@ -2064,6 +2074,7 @@ add_library(grpc_test_util_unsecure
src/core/lib/http/format_request.cc src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc src/core/lib/http/parser.cc
src/core/lib/iomgr/buffer_list.cc
src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint.cc src/core/lib/iomgr/endpoint.cc
@ -2084,6 +2095,7 @@ add_library(grpc_test_util_unsecure
src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_fallback.cc
src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_host_name_max.cc
src/core/lib/iomgr/gethostname_sysconf.cc src/core/lib/iomgr/gethostname_sysconf.cc
src/core/lib/iomgr/internal_errqueue.cc
src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iocp_windows.cc
src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_custom.cc src/core/lib/iomgr/iomgr_custom.cc
@ -2351,6 +2363,7 @@ add_library(grpc_unsecure
src/core/lib/http/format_request.cc src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc src/core/lib/http/parser.cc
src/core/lib/iomgr/buffer_list.cc
src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint.cc src/core/lib/iomgr/endpoint.cc
@ -2371,6 +2384,7 @@ add_library(grpc_unsecure
src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_fallback.cc
src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_host_name_max.cc
src/core/lib/iomgr/gethostname_sysconf.cc src/core/lib/iomgr/gethostname_sysconf.cc
src/core/lib/iomgr/internal_errqueue.cc
src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iocp_windows.cc
src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_custom.cc src/core/lib/iomgr/iomgr_custom.cc
@ -3191,6 +3205,7 @@ add_library(grpc++_cronet
src/core/lib/http/format_request.cc src/core/lib/http/format_request.cc
src/core/lib/http/httpcli.cc src/core/lib/http/httpcli.cc
src/core/lib/http/parser.cc src/core/lib/http/parser.cc
src/core/lib/iomgr/buffer_list.cc
src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/call_combiner.cc
src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/combiner.cc
src/core/lib/iomgr/endpoint.cc src/core/lib/iomgr/endpoint.cc
@ -3211,6 +3226,7 @@ add_library(grpc++_cronet
src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_fallback.cc
src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_host_name_max.cc
src/core/lib/iomgr/gethostname_sysconf.cc src/core/lib/iomgr/gethostname_sysconf.cc
src/core/lib/iomgr/internal_errqueue.cc
src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iocp_windows.cc
src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr.cc
src/core/lib/iomgr/iomgr_custom.cc src/core/lib/iomgr/iomgr_custom.cc
@ -5834,6 +5850,37 @@ target_link_libraries(bin_encoder_test
grpc grpc
) )
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX)
add_executable(buffer_list_test
test/core/iomgr/buffer_list_test.cc
)
target_include_directories(buffer_list_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(buffer_list_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif()
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
@ -7893,6 +7940,35 @@ target_link_libraries(init_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(inproc_callback_test
test/core/end2end/inproc_callback_test.cc
)
target_include_directories(inproc_callback_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(inproc_callback_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(invalid_call_argument_test add_executable(invalid_call_argument_test
test/core/end2end/invalid_call_argument_test.cc test/core/end2end/invalid_call_argument_test.cc
) )

@ -978,6 +978,7 @@ avl_test: $(BINDIR)/$(CONFIG)/avl_test
bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test
bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
buffer_list_test: $(BINDIR)/$(CONFIG)/buffer_list_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
check_epollexclusive: $(BINDIR)/$(CONFIG)/check_epollexclusive check_epollexclusive: $(BINDIR)/$(CONFIG)/check_epollexclusive
chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
@ -1053,6 +1054,7 @@ httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test
httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test
httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test
init_test: $(BINDIR)/$(CONFIG)/init_test init_test: $(BINDIR)/$(CONFIG)/init_test
inproc_callback_test: $(BINDIR)/$(CONFIG)/inproc_callback_test
invalid_call_argument_test: $(BINDIR)/$(CONFIG)/invalid_call_argument_test invalid_call_argument_test: $(BINDIR)/$(CONFIG)/invalid_call_argument_test
json_fuzzer_test: $(BINDIR)/$(CONFIG)/json_fuzzer_test json_fuzzer_test: $(BINDIR)/$(CONFIG)/json_fuzzer_test
json_rewrite: $(BINDIR)/$(CONFIG)/json_rewrite json_rewrite: $(BINDIR)/$(CONFIG)/json_rewrite
@ -1433,6 +1435,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/bad_server_response_test \ $(BINDIR)/$(CONFIG)/bad_server_response_test \
$(BINDIR)/$(CONFIG)/bin_decoder_test \ $(BINDIR)/$(CONFIG)/bin_decoder_test \
$(BINDIR)/$(CONFIG)/bin_encoder_test \ $(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/buffer_list_test \
$(BINDIR)/$(CONFIG)/channel_create_test \ $(BINDIR)/$(CONFIG)/channel_create_test \
$(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \ $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
$(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \
@ -1500,6 +1503,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/httpcli_test \ $(BINDIR)/$(CONFIG)/httpcli_test \
$(BINDIR)/$(CONFIG)/httpscli_test \ $(BINDIR)/$(CONFIG)/httpscli_test \
$(BINDIR)/$(CONFIG)/init_test \ $(BINDIR)/$(CONFIG)/init_test \
$(BINDIR)/$(CONFIG)/inproc_callback_test \
$(BINDIR)/$(CONFIG)/invalid_call_argument_test \ $(BINDIR)/$(CONFIG)/invalid_call_argument_test \
$(BINDIR)/$(CONFIG)/json_rewrite \ $(BINDIR)/$(CONFIG)/json_rewrite \
$(BINDIR)/$(CONFIG)/json_rewrite_test \ $(BINDIR)/$(CONFIG)/json_rewrite_test \
@ -1948,6 +1952,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 )
$(E) "[RUN] Testing bin_encoder_test" $(E) "[RUN] Testing bin_encoder_test"
$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
$(E) "[RUN] Testing buffer_list_test"
$(Q) $(BINDIR)/$(CONFIG)/buffer_list_test || ( echo test buffer_list_test failed ; exit 1 )
$(E) "[RUN] Testing channel_create_test" $(E) "[RUN] Testing channel_create_test"
$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_hpack_encoder_test" $(E) "[RUN] Testing chttp2_hpack_encoder_test"
@ -2076,6 +2082,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/httpscli_test || ( echo test httpscli_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/httpscli_test || ( echo test httpscli_test failed ; exit 1 )
$(E) "[RUN] Testing init_test" $(E) "[RUN] Testing init_test"
$(Q) $(BINDIR)/$(CONFIG)/init_test || ( echo test init_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/init_test || ( echo test init_test failed ; exit 1 )
$(E) "[RUN] Testing inproc_callback_test"
$(Q) $(BINDIR)/$(CONFIG)/inproc_callback_test || ( echo test inproc_callback_test failed ; exit 1 )
$(E) "[RUN] Testing invalid_call_argument_test" $(E) "[RUN] Testing invalid_call_argument_test"
$(Q) $(BINDIR)/$(CONFIG)/invalid_call_argument_test || ( echo test invalid_call_argument_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/invalid_call_argument_test || ( echo test invalid_call_argument_test failed ; exit 1 )
$(E) "[RUN] Testing json_rewrite_test" $(E) "[RUN] Testing json_rewrite_test"
@ -3456,6 +3464,7 @@ LIBGRPC_SRC = \
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -3476,6 +3485,7 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \
@ -3861,6 +3871,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -3881,6 +3892,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \
@ -4251,6 +4263,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -4271,6 +4284,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \
@ -4550,6 +4564,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -4570,6 +4585,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \
@ -4815,6 +4831,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -4835,6 +4852,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \
@ -5643,6 +5661,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -5663,6 +5682,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \
@ -10697,6 +10717,38 @@ endif
endif endif
BUFFER_LIST_TEST_SRC = \
test/core/iomgr/buffer_list_test.cc \
BUFFER_LIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BUFFER_LIST_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/buffer_list_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/buffer_list_test: $(BUFFER_LIST_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(BUFFER_LIST_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/buffer_list_test
endif
$(OBJDIR)/$(CONFIG)/test/core/iomgr/buffer_list_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_buffer_list_test: $(BUFFER_LIST_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BUFFER_LIST_TEST_OBJS:.o=.dep)
endif
endif
CHANNEL_CREATE_TEST_SRC = \ CHANNEL_CREATE_TEST_SRC = \
test/core/surface/channel_create_test.cc \ test/core/surface/channel_create_test.cc \
@ -13115,6 +13167,38 @@ endif
endif endif
INPROC_CALLBACK_TEST_SRC = \
test/core/end2end/inproc_callback_test.cc \
INPROC_CALLBACK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INPROC_CALLBACK_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/inproc_callback_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/inproc_callback_test: $(INPROC_CALLBACK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(INPROC_CALLBACK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/inproc_callback_test
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/inproc_callback_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_inproc_callback_test: $(INPROC_CALLBACK_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(INPROC_CALLBACK_TEST_OBJS:.o=.dep)
endif
endif
INVALID_CALL_ARGUMENT_TEST_SRC = \ INVALID_CALL_ARGUMENT_TEST_SRC = \
test/core/end2end/invalid_call_argument_test.cc \ test/core/end2end/invalid_call_argument_test.cc \

@ -256,6 +256,7 @@ filegroups:
- src/core/lib/http/format_request.cc - src/core/lib/http/format_request.cc
- src/core/lib/http/httpcli.cc - src/core/lib/http/httpcli.cc
- src/core/lib/http/parser.cc - src/core/lib/http/parser.cc
- src/core/lib/iomgr/buffer_list.cc
- src/core/lib/iomgr/call_combiner.cc - src/core/lib/iomgr/call_combiner.cc
- src/core/lib/iomgr/combiner.cc - src/core/lib/iomgr/combiner.cc
- src/core/lib/iomgr/endpoint.cc - src/core/lib/iomgr/endpoint.cc
@ -276,6 +277,7 @@ filegroups:
- src/core/lib/iomgr/gethostname_fallback.cc - src/core/lib/iomgr/gethostname_fallback.cc
- src/core/lib/iomgr/gethostname_host_name_max.cc - src/core/lib/iomgr/gethostname_host_name_max.cc
- src/core/lib/iomgr/gethostname_sysconf.cc - src/core/lib/iomgr/gethostname_sysconf.cc
- src/core/lib/iomgr/internal_errqueue.cc
- src/core/lib/iomgr/iocp_windows.cc - src/core/lib/iomgr/iocp_windows.cc
- src/core/lib/iomgr/iomgr.cc - src/core/lib/iomgr/iomgr.cc
- src/core/lib/iomgr/iomgr_custom.cc - src/core/lib/iomgr/iomgr_custom.cc
@ -434,6 +436,7 @@ filegroups:
- src/core/lib/http/httpcli.h - src/core/lib/http/httpcli.h
- src/core/lib/http/parser.h - src/core/lib/http/parser.h
- src/core/lib/iomgr/block_annotate.h - src/core/lib/iomgr/block_annotate.h
- src/core/lib/iomgr/buffer_list.h
- src/core/lib/iomgr/call_combiner.h - src/core/lib/iomgr/call_combiner.h
- src/core/lib/iomgr/closure.h - src/core/lib/iomgr/closure.h
- src/core/lib/iomgr/combiner.h - src/core/lib/iomgr/combiner.h
@ -449,6 +452,7 @@ filegroups:
- src/core/lib/iomgr/exec_ctx.h - src/core/lib/iomgr/exec_ctx.h
- src/core/lib/iomgr/executor.h - src/core/lib/iomgr/executor.h
- src/core/lib/iomgr/gethostname.h - src/core/lib/iomgr/gethostname.h
- src/core/lib/iomgr/internal_errqueue.h
- src/core/lib/iomgr/iocp_windows.h - src/core/lib/iomgr/iocp_windows.h
- src/core/lib/iomgr/iomgr.h - src/core/lib/iomgr/iomgr.h
- src/core/lib/iomgr/iomgr_custom.h - src/core/lib/iomgr/iomgr_custom.h
@ -2139,6 +2143,20 @@ targets:
- grpc_test_util - grpc_test_util
- grpc - grpc
uses_polling: false uses_polling: false
- name: buffer_list_test
build: test
language: c
src:
- test/core/iomgr/buffer_list_test.cc
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
exclude_iomgrs:
- uv
platforms:
- linux
- name: channel_create_test - name: channel_create_test
build: test build: test
language: c language: c
@ -3022,6 +3040,19 @@ targets:
- gpr_test_util - gpr_test_util
- gpr - gpr
uses_polling: false uses_polling: false
- name: inproc_callback_test
build: test
language: c
headers:
- test/core/end2end/end2end_tests.h
src:
- test/core/end2end/inproc_callback_test.cc
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
uses_polling: false
- name: invalid_call_argument_test - name: invalid_call_argument_test
cpu_cost: 0.1 cpu_cost: 0.1
build: test build: test

@ -108,6 +108,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/http/format_request.cc \ src/core/lib/http/format_request.cc \
src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli.cc \
src/core/lib/http/parser.cc \ src/core/lib/http/parser.cc \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/combiner.cc \
src/core/lib/iomgr/endpoint.cc \ src/core/lib/iomgr/endpoint.cc \
@ -128,6 +129,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \
src/core/lib/iomgr/iomgr_custom.cc \ src/core/lib/iomgr/iomgr_custom.cc \

@ -83,6 +83,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\http\\format_request.cc " + "src\\core\\lib\\http\\format_request.cc " +
"src\\core\\lib\\http\\httpcli.cc " + "src\\core\\lib\\http\\httpcli.cc " +
"src\\core\\lib\\http\\parser.cc " + "src\\core\\lib\\http\\parser.cc " +
"src\\core\\lib\\iomgr\\buffer_list.cc " +
"src\\core\\lib\\iomgr\\call_combiner.cc " + "src\\core\\lib\\iomgr\\call_combiner.cc " +
"src\\core\\lib\\iomgr\\combiner.cc " + "src\\core\\lib\\iomgr\\combiner.cc " +
"src\\core\\lib\\iomgr\\endpoint.cc " + "src\\core\\lib\\iomgr\\endpoint.cc " +
@ -103,6 +104,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\iomgr\\gethostname_fallback.cc " + "src\\core\\lib\\iomgr\\gethostname_fallback.cc " +
"src\\core\\lib\\iomgr\\gethostname_host_name_max.cc " + "src\\core\\lib\\iomgr\\gethostname_host_name_max.cc " +
"src\\core\\lib\\iomgr\\gethostname_sysconf.cc " + "src\\core\\lib\\iomgr\\gethostname_sysconf.cc " +
"src\\core\\lib\\iomgr\\internal_errqueue.cc " +
"src\\core\\lib\\iomgr\\iocp_windows.cc " + "src\\core\\lib\\iomgr\\iocp_windows.cc " +
"src\\core\\lib\\iomgr\\iomgr.cc " + "src\\core\\lib\\iomgr\\iomgr.cc " +
"src\\core\\lib\\iomgr\\iomgr_custom.cc " + "src\\core\\lib\\iomgr\\iomgr_custom.cc " +

@ -382,6 +382,7 @@ Pod::Spec.new do |s|
'src/core/lib/http/httpcli.h', 'src/core/lib/http/httpcli.h',
'src/core/lib/http/parser.h', 'src/core/lib/http/parser.h',
'src/core/lib/iomgr/block_annotate.h', 'src/core/lib/iomgr/block_annotate.h',
'src/core/lib/iomgr/buffer_list.h',
'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/call_combiner.h',
'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/closure.h',
'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/combiner.h',
@ -397,6 +398,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h', 'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr.h',
'src/core/lib/iomgr/iomgr_custom.h', 'src/core/lib/iomgr/iomgr_custom.h',
@ -570,6 +572,7 @@ Pod::Spec.new do |s|
'src/core/lib/http/httpcli.h', 'src/core/lib/http/httpcli.h',
'src/core/lib/http/parser.h', 'src/core/lib/http/parser.h',
'src/core/lib/iomgr/block_annotate.h', 'src/core/lib/iomgr/block_annotate.h',
'src/core/lib/iomgr/buffer_list.h',
'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/call_combiner.h',
'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/closure.h',
'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/combiner.h',
@ -585,6 +588,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h', 'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr.h',
'src/core/lib/iomgr/iomgr_custom.h', 'src/core/lib/iomgr/iomgr_custom.h',

@ -394,6 +394,7 @@ Pod::Spec.new do |s|
'src/core/lib/http/httpcli.h', 'src/core/lib/http/httpcli.h',
'src/core/lib/http/parser.h', 'src/core/lib/http/parser.h',
'src/core/lib/iomgr/block_annotate.h', 'src/core/lib/iomgr/block_annotate.h',
'src/core/lib/iomgr/buffer_list.h',
'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/call_combiner.h',
'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/closure.h',
'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/combiner.h',
@ -409,6 +410,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h', 'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr.h',
'src/core/lib/iomgr/iomgr_custom.h', 'src/core/lib/iomgr/iomgr_custom.h',
@ -538,6 +540,7 @@ Pod::Spec.new do |s|
'src/core/lib/http/format_request.cc', 'src/core/lib/http/format_request.cc',
'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli.cc',
'src/core/lib/http/parser.cc', 'src/core/lib/http/parser.cc',
'src/core/lib/iomgr/buffer_list.cc',
'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/call_combiner.cc',
'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/combiner.cc',
'src/core/lib/iomgr/endpoint.cc', 'src/core/lib/iomgr/endpoint.cc',
@ -558,6 +561,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_fallback.cc',
'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc',
'src/core/lib/iomgr/gethostname_sysconf.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc',
'src/core/lib/iomgr/internal_errqueue.cc',
'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iocp_windows.cc',
'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr.cc',
'src/core/lib/iomgr/iomgr_custom.cc', 'src/core/lib/iomgr/iomgr_custom.cc',
@ -993,6 +997,7 @@ Pod::Spec.new do |s|
'src/core/lib/http/httpcli.h', 'src/core/lib/http/httpcli.h',
'src/core/lib/http/parser.h', 'src/core/lib/http/parser.h',
'src/core/lib/iomgr/block_annotate.h', 'src/core/lib/iomgr/block_annotate.h',
'src/core/lib/iomgr/buffer_list.h',
'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/call_combiner.h',
'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/closure.h',
'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/combiner.h',
@ -1008,6 +1013,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h', 'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr.h',
'src/core/lib/iomgr/iomgr_custom.h', 'src/core/lib/iomgr/iomgr_custom.h',

@ -330,6 +330,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/httpcli.h )
s.files += %w( src/core/lib/http/parser.h ) s.files += %w( src/core/lib/http/parser.h )
s.files += %w( src/core/lib/iomgr/block_annotate.h ) s.files += %w( src/core/lib/iomgr/block_annotate.h )
s.files += %w( src/core/lib/iomgr/buffer_list.h )
s.files += %w( src/core/lib/iomgr/call_combiner.h ) s.files += %w( src/core/lib/iomgr/call_combiner.h )
s.files += %w( src/core/lib/iomgr/closure.h ) s.files += %w( src/core/lib/iomgr/closure.h )
s.files += %w( src/core/lib/iomgr/combiner.h ) s.files += %w( src/core/lib/iomgr/combiner.h )
@ -345,6 +346,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/exec_ctx.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h )
s.files += %w( src/core/lib/iomgr/executor.h ) s.files += %w( src/core/lib/iomgr/executor.h )
s.files += %w( src/core/lib/iomgr/gethostname.h ) s.files += %w( src/core/lib/iomgr/gethostname.h )
s.files += %w( src/core/lib/iomgr/internal_errqueue.h )
s.files += %w( src/core/lib/iomgr/iocp_windows.h ) s.files += %w( src/core/lib/iomgr/iocp_windows.h )
s.files += %w( src/core/lib/iomgr/iomgr.h ) s.files += %w( src/core/lib/iomgr/iomgr.h )
s.files += %w( src/core/lib/iomgr/iomgr_custom.h ) s.files += %w( src/core/lib/iomgr/iomgr_custom.h )
@ -474,6 +476,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/http/format_request.cc ) s.files += %w( src/core/lib/http/format_request.cc )
s.files += %w( src/core/lib/http/httpcli.cc ) s.files += %w( src/core/lib/http/httpcli.cc )
s.files += %w( src/core/lib/http/parser.cc ) s.files += %w( src/core/lib/http/parser.cc )
s.files += %w( src/core/lib/iomgr/buffer_list.cc )
s.files += %w( src/core/lib/iomgr/call_combiner.cc ) s.files += %w( src/core/lib/iomgr/call_combiner.cc )
s.files += %w( src/core/lib/iomgr/combiner.cc ) s.files += %w( src/core/lib/iomgr/combiner.cc )
s.files += %w( src/core/lib/iomgr/endpoint.cc ) s.files += %w( src/core/lib/iomgr/endpoint.cc )
@ -494,6 +497,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/gethostname_fallback.cc ) s.files += %w( src/core/lib/iomgr/gethostname_fallback.cc )
s.files += %w( src/core/lib/iomgr/gethostname_host_name_max.cc ) s.files += %w( src/core/lib/iomgr/gethostname_host_name_max.cc )
s.files += %w( src/core/lib/iomgr/gethostname_sysconf.cc ) s.files += %w( src/core/lib/iomgr/gethostname_sysconf.cc )
s.files += %w( src/core/lib/iomgr/internal_errqueue.cc )
s.files += %w( src/core/lib/iomgr/iocp_windows.cc ) s.files += %w( src/core/lib/iomgr/iocp_windows.cc )
s.files += %w( src/core/lib/iomgr/iomgr.cc ) s.files += %w( src/core/lib/iomgr/iomgr.cc )
s.files += %w( src/core/lib/iomgr/iomgr_custom.cc ) s.files += %w( src/core/lib/iomgr/iomgr_custom.cc )

@ -300,6 +300,7 @@
'src/core/lib/http/format_request.cc', 'src/core/lib/http/format_request.cc',
'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli.cc',
'src/core/lib/http/parser.cc', 'src/core/lib/http/parser.cc',
'src/core/lib/iomgr/buffer_list.cc',
'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/call_combiner.cc',
'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/combiner.cc',
'src/core/lib/iomgr/endpoint.cc', 'src/core/lib/iomgr/endpoint.cc',
@ -320,6 +321,7 @@
'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_fallback.cc',
'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc',
'src/core/lib/iomgr/gethostname_sysconf.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc',
'src/core/lib/iomgr/internal_errqueue.cc',
'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iocp_windows.cc',
'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr.cc',
'src/core/lib/iomgr/iomgr_custom.cc', 'src/core/lib/iomgr/iomgr_custom.cc',
@ -660,6 +662,7 @@
'src/core/lib/http/format_request.cc', 'src/core/lib/http/format_request.cc',
'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli.cc',
'src/core/lib/http/parser.cc', 'src/core/lib/http/parser.cc',
'src/core/lib/iomgr/buffer_list.cc',
'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/call_combiner.cc',
'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/combiner.cc',
'src/core/lib/iomgr/endpoint.cc', 'src/core/lib/iomgr/endpoint.cc',
@ -680,6 +683,7 @@
'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_fallback.cc',
'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc',
'src/core/lib/iomgr/gethostname_sysconf.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc',
'src/core/lib/iomgr/internal_errqueue.cc',
'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iocp_windows.cc',
'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr.cc',
'src/core/lib/iomgr/iomgr_custom.cc', 'src/core/lib/iomgr/iomgr_custom.cc',
@ -893,6 +897,7 @@
'src/core/lib/http/format_request.cc', 'src/core/lib/http/format_request.cc',
'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli.cc',
'src/core/lib/http/parser.cc', 'src/core/lib/http/parser.cc',
'src/core/lib/iomgr/buffer_list.cc',
'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/call_combiner.cc',
'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/combiner.cc',
'src/core/lib/iomgr/endpoint.cc', 'src/core/lib/iomgr/endpoint.cc',
@ -913,6 +918,7 @@
'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_fallback.cc',
'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc',
'src/core/lib/iomgr/gethostname_sysconf.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc',
'src/core/lib/iomgr/internal_errqueue.cc',
'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iocp_windows.cc',
'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr.cc',
'src/core/lib/iomgr/iomgr_custom.cc', 'src/core/lib/iomgr/iomgr_custom.cc',
@ -1104,6 +1110,7 @@
'src/core/lib/http/format_request.cc', 'src/core/lib/http/format_request.cc',
'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli.cc',
'src/core/lib/http/parser.cc', 'src/core/lib/http/parser.cc',
'src/core/lib/iomgr/buffer_list.cc',
'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/call_combiner.cc',
'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/combiner.cc',
'src/core/lib/iomgr/endpoint.cc', 'src/core/lib/iomgr/endpoint.cc',
@ -1124,6 +1131,7 @@
'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_fallback.cc',
'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc',
'src/core/lib/iomgr/gethostname_sysconf.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc',
'src/core/lib/iomgr/internal_errqueue.cc',
'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iocp_windows.cc',
'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr.cc',
'src/core/lib/iomgr/iomgr_custom.cc', 'src/core/lib/iomgr/iomgr_custom.cc',

@ -335,6 +335,7 @@
<file baseinstalldir="/" name="src/core/lib/http/httpcli.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/httpcli.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/parser.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/parser.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/block_annotate.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/block_annotate.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/buffer_list.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/call_combiner.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/call_combiner.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/closure.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/closure.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/combiner.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/combiner.h" role="src" />
@ -350,6 +351,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/executor.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/executor.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/gethostname.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/internal_errqueue.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_custom.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_custom.h" role="src" />
@ -479,6 +481,7 @@
<file baseinstalldir="/" name="src/core/lib/http/format_request.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/format_request.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/httpcli.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/httpcli.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/parser.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/parser.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/buffer_list.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/call_combiner.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/call_combiner.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/combiner.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/combiner.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.cc" role="src" />
@ -499,6 +502,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_fallback.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_fallback.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_host_name_max.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_host_name_max.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_sysconf.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_sysconf.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/internal_errqueue.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_custom.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_custom.cc" role="src" />

@ -320,7 +320,7 @@ static void http_connect_handshaker_do_handshake(
// Take a new ref to be held by the write callback. // Take a new ref to be held by the write callback.
gpr_ref(&handshaker->refcount); gpr_ref(&handshaker->refcount);
grpc_endpoint_write(args->endpoint, &handshaker->write_buffer, grpc_endpoint_write(args->endpoint, &handshaker->write_buffer,
&handshaker->request_done_closure); &handshaker->request_done_closure, nullptr);
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
} }

@ -50,7 +50,7 @@ grpc_channel* grpc_insecure_channel_create_from_fd(
GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
grpc_endpoint* client = grpc_tcp_client_create_from_fd( grpc_endpoint* client = grpc_tcp_client_create_from_fd(
grpc_fd_create(fd, "client", false), args, "fd-client"); grpc_fd_create(fd, "client", true), args, "fd-client");
grpc_transport* transport = grpc_transport* transport =
grpc_create_chttp2_transport(final_args, client, true); grpc_create_chttp2_transport(final_args, client, true);

@ -44,7 +44,7 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server* server,
gpr_asprintf(&name, "fd:%d", fd); gpr_asprintf(&name, "fd:%d", fd);
grpc_endpoint* server_endpoint = grpc_endpoint* server_endpoint =
grpc_tcp_create(grpc_fd_create(fd, name, false), grpc_tcp_create(grpc_fd_create(fd, name, true),
grpc_server_get_channel_args(server), name); grpc_server_get_channel_args(server), name);
gpr_free(name); gpr_free(name);

@ -1029,7 +1029,8 @@ static void write_action(void* gt, grpc_error* error) {
grpc_endpoint_write( grpc_endpoint_write(
t->ep, &t->outbuf, t->ep, &t->outbuf,
GRPC_CLOSURE_INIT(&t->write_action_end_locked, write_action_end_locked, t, GRPC_CLOSURE_INIT(&t->write_action_end_locked, write_action_end_locked, t,
grpc_combiner_scheduler(t->combiner))); grpc_combiner_scheduler(t->combiner)),
nullptr);
} }
/* Callback from the grpc_endpoint after bytes have been written by calling /* Callback from the grpc_endpoint after bytes have been written by calling

@ -163,7 +163,7 @@ static void done_write(void* arg, grpc_error* error) {
static void start_write(internal_request* req) { static void start_write(internal_request* req) {
grpc_slice_ref_internal(req->request_text); grpc_slice_ref_internal(req->request_text);
grpc_slice_buffer_add(&req->outgoing, req->request_text); grpc_slice_buffer_add(&req->outgoing, req->request_text);
grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write); grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write, nullptr);
} }
static void on_handshake_done(void* arg, grpc_endpoint* ep) { static void on_handshake_done(void* arg, grpc_endpoint* ep) {

@ -0,0 +1,134 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/buffer_list.h"
#include "src/core/lib/iomgr/port.h"
#include <grpc/support/log.h>
#ifdef GRPC_LINUX_ERRQUEUE
#include <time.h>
#include "src/core/lib/gprpp/memory.h"
namespace grpc_core {
void TracedBuffer::AddNewEntry(TracedBuffer** head, uint32_t seq_no,
void* arg) {
GPR_DEBUG_ASSERT(head != nullptr);
TracedBuffer* new_elem = New<TracedBuffer>(seq_no, arg);
/* Store the current time as the sendmsg time. */
new_elem->ts_.sendmsg_time = gpr_now(GPR_CLOCK_REALTIME);
if (*head == nullptr) {
*head = new_elem;
return;
}
/* Append at the end. */
TracedBuffer* ptr = *head;
while (ptr->next_ != nullptr) {
ptr = ptr->next_;
}
ptr->next_ = new_elem;
}
namespace {
/** Fills gpr_timespec gts based on values from timespec ts */
void fill_gpr_from_timestamp(gpr_timespec* gts, const struct timespec* ts) {
gts->tv_sec = ts->tv_sec;
gts->tv_nsec = static_cast<int32_t>(ts->tv_nsec);
gts->clock_type = GPR_CLOCK_REALTIME;
}
/** The saved callback function that will be invoked when we get all the
* timestamps that we are going to get for a TracedBuffer. */
void (*timestamps_callback)(void*, grpc_core::Timestamps*,
grpc_error* shutdown_err);
} /* namespace */
void TracedBuffer::ProcessTimestamp(TracedBuffer** head,
struct sock_extended_err* serr,
struct scm_timestamping* tss) {
GPR_DEBUG_ASSERT(head != nullptr);
TracedBuffer* elem = *head;
TracedBuffer* next = nullptr;
while (elem != nullptr) {
/* The byte number refers to the sequence number of the last byte which this
* timestamp relates to. */
if (serr->ee_data >= elem->seq_no_) {
switch (serr->ee_info) {
case SCM_TSTAMP_SCHED:
fill_gpr_from_timestamp(&(elem->ts_.scheduled_time), &(tss->ts[0]));
elem = elem->next_;
break;
case SCM_TSTAMP_SND:
fill_gpr_from_timestamp(&(elem->ts_.sent_time), &(tss->ts[0]));
elem = elem->next_;
break;
case SCM_TSTAMP_ACK:
fill_gpr_from_timestamp(&(elem->ts_.acked_time), &(tss->ts[0]));
/* Got all timestamps. Do the callback and free this TracedBuffer.
* The thing below can be passed by value if we don't want the
* restriction on the lifetime. */
timestamps_callback(elem->arg_, &(elem->ts_), GRPC_ERROR_NONE);
next = elem->next_;
Delete<TracedBuffer>(elem);
*head = elem = next;
break;
default:
abort();
}
} else {
break;
}
}
}
void TracedBuffer::Shutdown(TracedBuffer** head, grpc_error* shutdown_err) {
GPR_DEBUG_ASSERT(head != nullptr);
TracedBuffer* elem = *head;
while (elem != nullptr) {
if (timestamps_callback) {
timestamps_callback(elem->arg_, &(elem->ts_), shutdown_err);
}
auto* next = elem->next_;
Delete<TracedBuffer>(elem);
elem = next;
}
*head = nullptr;
GRPC_ERROR_UNREF(shutdown_err);
}
void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*,
grpc_core::Timestamps*,
grpc_error* error)) {
timestamps_callback = fn;
}
} /* namespace grpc_core */
#else /* GRPC_LINUX_ERRQUEUE */
namespace grpc_core {
void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*,
grpc_core::Timestamps*,
grpc_error* error)) {
gpr_log(GPR_DEBUG, "Timestamps callback is not enabled for this platform");
}
} /* namespace grpc_core */
#endif /* GRPC_LINUX_ERRQUEUE */

@ -0,0 +1,96 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H
#define GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#include <grpc/support/time.h>
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/internal_errqueue.h"
namespace grpc_core {
struct Timestamps {
/* TODO(yashykt): This would also need to store OPTSTAT once support is added
*/
gpr_timespec sendmsg_time;
gpr_timespec scheduled_time;
gpr_timespec sent_time;
gpr_timespec acked_time;
};
/** TracedBuffer is a class to keep track of timestamps for a specific buffer in
* the TCP layer. We are only tracking timestamps for Linux kernels and hence
* this class would only be used by Linux platforms. For all other platforms,
* TracedBuffer would be an empty class.
*
* The timestamps collected are according to grpc_core::Timestamps declared
* above.
*
* A TracedBuffer list is kept track of using the head element of the list. If
* the head element of the list is nullptr, then the list is empty.
*/
#ifdef GRPC_LINUX_ERRQUEUE
class TracedBuffer {
public:
/** Add a new entry in the TracedBuffer list pointed to by head. Also saves
* sendmsg_time with the current timestamp. */
static void AddNewEntry(grpc_core::TracedBuffer** head, uint32_t seq_no,
void* arg);
/** Processes a received timestamp based on sock_extended_err and
* scm_timestamping structures. It will invoke the timestamps callback if the
* timestamp type is SCM_TSTAMP_ACK. */
static void ProcessTimestamp(grpc_core::TracedBuffer** head,
struct sock_extended_err* serr,
struct scm_timestamping* tss);
/** Cleans the list by calling the callback for each traced buffer in the list
* with timestamps that it has. */
static void Shutdown(grpc_core::TracedBuffer** head,
grpc_error* shutdown_err);
private:
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW
TracedBuffer(int seq_no, void* arg)
: seq_no_(seq_no), arg_(arg), next_(nullptr) {}
uint32_t seq_no_; /* The sequence number for the last byte in the buffer */
void* arg_; /* The arg to pass to timestamps_callback */
grpc_core::Timestamps ts_; /* The timestamps corresponding to this buffer */
grpc_core::TracedBuffer* next_; /* The next TracedBuffer in the list */
};
#else /* GRPC_LINUX_ERRQUEUE */
class TracedBuffer {};
#endif /* GRPC_LINUX_ERRQUEUE */
/** Sets the callback function to call when timestamps for a write are
* collected. The callback does not own a reference to error. */
void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*,
grpc_core::Timestamps*,
grpc_error* error));
}; /* namespace grpc_core */
#endif /* GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H */

@ -28,8 +28,8 @@ void grpc_endpoint_read(grpc_endpoint* ep, grpc_slice_buffer* slices,
} }
void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
ep->vtable->write(ep, slices, cb); ep->vtable->write(ep, slices, cb, arg);
} }
void grpc_endpoint_add_to_pollset(grpc_endpoint* ep, grpc_pollset* pollset) { void grpc_endpoint_add_to_pollset(grpc_endpoint* ep, grpc_pollset* pollset) {

@ -33,10 +33,12 @@
typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint grpc_endpoint;
typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable;
class Timestamps;
struct grpc_endpoint_vtable { struct grpc_endpoint_vtable {
void (*read)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb); void (*read)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb);
void (*write)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb); void (*write)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb,
void* arg);
void (*add_to_pollset)(grpc_endpoint* ep, grpc_pollset* pollset); void (*add_to_pollset)(grpc_endpoint* ep, grpc_pollset* pollset);
void (*add_to_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); void (*add_to_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset);
void (*delete_from_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); void (*delete_from_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset);
@ -70,9 +72,11 @@ int grpc_endpoint_get_fd(grpc_endpoint* ep);
\a slices may be mutated at will by the endpoint until cb is called. \a slices may be mutated at will by the endpoint until cb is called.
No guarantee is made to the content of slices after a write EXCEPT that No guarantee is made to the content of slices after a write EXCEPT that
it is a valid slice buffer. it is a valid slice buffer.
\a arg is platform specific. It is currently only used by TCP on linux
platforms as an argument that would be forwarded to the timestamps callback.
*/ */
void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb); grpc_closure* cb, void* arg);
/* Causes any pending and future read/write callbacks to run immediately with /* Causes any pending and future read/write callbacks to run immediately with
success==0 */ success==0 */

@ -268,7 +268,7 @@ static void CFStreamRead(grpc_endpoint* ep, grpc_slice_buffer* slices,
} }
static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices, static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
if (grpc_tcp_trace.enabled()) { if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p write (%p, %p) length:%zu", gpr_log(GPR_DEBUG, "CFStream endpoint:%p write (%p, %p) length:%zu",

@ -59,11 +59,11 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char* name,
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
gpr_asprintf(&final_name, "%s:client", name); gpr_asprintf(&final_name, "%s:client", name);
p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name, false), args, p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name, true), args,
"socketpair-server"); "socketpair-server");
gpr_free(final_name); gpr_free(final_name);
gpr_asprintf(&final_name, "%s:server", name); gpr_asprintf(&final_name, "%s:server", name);
p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name, false), args, p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name, true), args,
"socketpair-client"); "socketpair-client");
gpr_free(final_name); gpr_free(final_name);

@ -60,6 +60,19 @@ typedef struct grpc_fd_watcher {
grpc_fd* fd; grpc_fd* fd;
} grpc_fd_watcher; } grpc_fd_watcher;
typedef struct grpc_cached_wakeup_fd grpc_cached_wakeup_fd;
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
struct grpc_fork_fd_list {
/* Only one of fd or cached_wakeup_fd will be set. The unused field will be
set to nullptr. */
grpc_fd* fd;
grpc_cached_wakeup_fd* cached_wakeup_fd;
grpc_fork_fd_list* next;
grpc_fork_fd_list* prev;
};
struct grpc_fd { struct grpc_fd {
int fd; int fd;
/* refst format: /* refst format:
@ -108,8 +121,18 @@ struct grpc_fd {
grpc_closure* on_done_closure; grpc_closure* on_done_closure;
grpc_iomgr_object iomgr_object; grpc_iomgr_object iomgr_object;
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
grpc_fork_fd_list* fork_fd_list;
}; };
/* True when GRPC_ENABLE_FORK_SUPPORT=1. We do not support fork with poll-cv */
static bool track_fds_for_fork = false;
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
static grpc_fork_fd_list* fork_fd_list_head = nullptr;
static gpr_mu fork_fd_list_mu;
/* Begin polling on an fd. /* Begin polling on an fd.
Registers that the given pollset is interested in this fd - so that if read Registers that the given pollset is interested in this fd - so that if read
or writability interest changes, the pollset can be kicked to pick up that or writability interest changes, the pollset can be kicked to pick up that
@ -156,6 +179,9 @@ static void fd_unref(grpc_fd* fd);
typedef struct grpc_cached_wakeup_fd { typedef struct grpc_cached_wakeup_fd {
grpc_wakeup_fd fd; grpc_wakeup_fd fd;
struct grpc_cached_wakeup_fd* next; struct grpc_cached_wakeup_fd* next;
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
grpc_fork_fd_list* fork_fd_list;
} grpc_cached_wakeup_fd; } grpc_cached_wakeup_fd;
struct grpc_pollset_worker { struct grpc_pollset_worker {
@ -281,9 +307,61 @@ poll_hash_table poll_cache;
grpc_cv_fd_table g_cvfds; grpc_cv_fd_table g_cvfds;
/******************************************************************************* /*******************************************************************************
* fd_posix.c * functions to track opened fds. No-ops unless track_fds_for_fork is true.
*/ */
static void fork_fd_list_remove_node(grpc_fork_fd_list* node) {
if (track_fds_for_fork) {
gpr_mu_lock(&fork_fd_list_mu);
if (fork_fd_list_head == node) {
fork_fd_list_head = node->next;
}
if (node->prev != nullptr) {
node->prev->next = node->next;
}
if (node->next != nullptr) {
node->next->prev = node->prev;
}
gpr_free(node);
gpr_mu_unlock(&fork_fd_list_mu);
}
}
static void fork_fd_list_add_node(grpc_fork_fd_list* node) {
gpr_mu_lock(&fork_fd_list_mu);
node->next = fork_fd_list_head;
node->prev = nullptr;
if (fork_fd_list_head != nullptr) {
fork_fd_list_head->prev = node;
}
fork_fd_list_head = node;
gpr_mu_unlock(&fork_fd_list_mu);
}
static void fork_fd_list_add_grpc_fd(grpc_fd* fd) {
if (track_fds_for_fork) {
fd->fork_fd_list =
static_cast<grpc_fork_fd_list*>(gpr_malloc(sizeof(grpc_fork_fd_list)));
fd->fork_fd_list->fd = fd;
fd->fork_fd_list->cached_wakeup_fd = nullptr;
fork_fd_list_add_node(fd->fork_fd_list);
}
}
static void fork_fd_list_add_wakeup_fd(grpc_cached_wakeup_fd* fd) {
if (track_fds_for_fork) {
fd->fork_fd_list =
static_cast<grpc_fork_fd_list*>(gpr_malloc(sizeof(grpc_fork_fd_list)));
fd->fork_fd_list->cached_wakeup_fd = fd;
fd->fork_fd_list->fd = nullptr;
fork_fd_list_add_node(fd->fork_fd_list);
}
}
/*******************************************************************************
* fd_posix.c
*/
#ifndef NDEBUG #ifndef NDEBUG
#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__)
@ -319,6 +397,7 @@ static void unref_by(grpc_fd* fd, int n) {
if (old == n) { if (old == n) {
gpr_mu_destroy(&fd->mu); gpr_mu_destroy(&fd->mu);
grpc_iomgr_unregister_object(&fd->iomgr_object); grpc_iomgr_unregister_object(&fd->iomgr_object);
fork_fd_list_remove_node(fd->fork_fd_list);
if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error); if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error);
gpr_free(fd); gpr_free(fd);
} else { } else {
@ -347,6 +426,7 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
gpr_asprintf(&name2, "%s fd=%d", name, fd); gpr_asprintf(&name2, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&r->iomgr_object, name2); grpc_iomgr_register_object(&r->iomgr_object, name2);
gpr_free(name2); gpr_free(name2);
fork_fd_list_add_grpc_fd(r);
return r; return r;
} }
@ -822,6 +902,7 @@ static void pollset_destroy(grpc_pollset* pollset) {
GPR_ASSERT(!pollset_has_workers(pollset)); GPR_ASSERT(!pollset_has_workers(pollset));
while (pollset->local_wakeup_cache) { while (pollset->local_wakeup_cache) {
grpc_cached_wakeup_fd* next = pollset->local_wakeup_cache->next; grpc_cached_wakeup_fd* next = pollset->local_wakeup_cache->next;
fork_fd_list_remove_node(pollset->local_wakeup_cache->fork_fd_list);
grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd); grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd);
gpr_free(pollset->local_wakeup_cache); gpr_free(pollset->local_wakeup_cache);
pollset->local_wakeup_cache = next; pollset->local_wakeup_cache = next;
@ -895,6 +976,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset,
worker.wakeup_fd = static_cast<grpc_cached_wakeup_fd*>( worker.wakeup_fd = static_cast<grpc_cached_wakeup_fd*>(
gpr_malloc(sizeof(*worker.wakeup_fd))); gpr_malloc(sizeof(*worker.wakeup_fd)));
error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd); error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
fork_fd_list_add_wakeup_fd(worker.wakeup_fd);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error));
return error; return error;
@ -1705,6 +1787,10 @@ static void shutdown_engine(void) {
if (grpc_cv_wakeup_fds_enabled()) { if (grpc_cv_wakeup_fds_enabled()) {
global_cv_fd_table_shutdown(); global_cv_fd_table_shutdown();
} }
if (track_fds_for_fork) {
gpr_mu_destroy(&fork_fd_list_mu);
grpc_core::Fork::SetResetChildPollingEngineFunc(nullptr);
}
} }
static const grpc_event_engine_vtable vtable = { static const grpc_event_engine_vtable vtable = {
@ -1742,6 +1828,26 @@ static const grpc_event_engine_vtable vtable = {
shutdown_engine, shutdown_engine,
}; };
/* Called by the child process's post-fork handler to close open fds, including
* worker wakeup fds. This allows gRPC to shutdown in the child process without
* interfering with connections or RPCs ongoing in the parent. */
static void reset_event_manager_on_fork() {
gpr_mu_lock(&fork_fd_list_mu);
while (fork_fd_list_head != nullptr) {
if (fork_fd_list_head->fd != nullptr) {
close(fork_fd_list_head->fd->fd);
fork_fd_list_head->fd->fd = -1;
} else {
close(fork_fd_list_head->cached_wakeup_fd->fd.read_fd);
fork_fd_list_head->cached_wakeup_fd->fd.read_fd = -1;
close(fork_fd_list_head->cached_wakeup_fd->fd.write_fd);
fork_fd_list_head->cached_wakeup_fd->fd.write_fd = -1;
}
fork_fd_list_head = fork_fd_list_head->next;
}
gpr_mu_unlock(&fork_fd_list_mu);
}
const grpc_event_engine_vtable* grpc_init_poll_posix(bool explicit_request) { const grpc_event_engine_vtable* grpc_init_poll_posix(bool explicit_request) {
if (!grpc_has_wakeup_fd()) { if (!grpc_has_wakeup_fd()) {
gpr_log(GPR_ERROR, "Skipping poll because of no wakeup fd."); gpr_log(GPR_ERROR, "Skipping poll because of no wakeup fd.");
@ -1750,6 +1856,12 @@ const grpc_event_engine_vtable* grpc_init_poll_posix(bool explicit_request) {
if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
return nullptr; return nullptr;
} }
if (grpc_core::Fork::Enabled()) {
track_fds_for_fork = true;
gpr_mu_init(&fork_fd_list_mu);
grpc_core::Fork::SetResetChildPollingEngineFunc(
reset_event_manager_on_fork);
}
return &vtable; return &vtable;
} }

@ -237,14 +237,19 @@ void grpc_event_engine_shutdown(void) {
} }
bool grpc_event_engine_can_track_errors(void) { bool grpc_event_engine_can_track_errors(void) {
/* Only track errors if platform supports errqueue. */
#ifdef GRPC_LINUX_ERRQUEUE
return g_event_engine->can_track_err; return g_event_engine->can_track_err;
#else
return false;
#endif /* GRPC_LINUX_ERRQUEUE */
} }
grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err) { grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err) {
GRPC_POLLING_API_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); GRPC_POLLING_API_TRACE("fd_create(%d, %s, %d)", fd, name, track_err);
GRPC_FD_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); GRPC_FD_TRACE("fd_create(%d, %s, %d)", fd, name, track_err);
GPR_DEBUG_ASSERT(!track_err || g_event_engine->can_track_err); return g_event_engine->fd_create(fd, name,
return g_event_engine->fd_create(fd, name, track_err); track_err && g_event_engine->can_track_err);
} }
int grpc_fd_wrapped_fd(grpc_fd* fd) { int grpc_fd_wrapped_fd(grpc_fd* fd) {

@ -58,6 +58,12 @@ void grpc_prefork() {
"environment variable GRPC_ENABLE_FORK_SUPPORT=1"); "environment variable GRPC_ENABLE_FORK_SUPPORT=1");
return; return;
} }
if (strcmp(grpc_get_poll_strategy_name(), "epoll1") != 0 &&
strcmp(grpc_get_poll_strategy_name(), "poll") != 0) {
gpr_log(GPR_ERROR,
"Fork support is only compatible with the epoll1 and poll polling "
"strategies");
}
if (!grpc_core::Fork::BlockExecCtx()) { if (!grpc_core::Fork::BlockExecCtx()) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"Other threads are currently calling into gRPC, skipping fork() " "Other threads are currently calling into gRPC, skipping fork() "

@ -0,0 +1,40 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#include "src/core/lib/iomgr/internal_errqueue.h"
#ifdef GRPC_POSIX_SOCKET_TCP
#ifdef GPR_LINUX
#include <linux/version.h>
#endif /* GPR_LINUX */
bool kernel_supports_errqueue() {
#ifdef LINUX_VERSION_CODE
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
return true;
#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(4, 0, 0) */
#endif /* LINUX_VERSION_CODE */
return false;
}
#endif /* GRPC_POSIX_SOCKET_TCP */

@ -0,0 +1,62 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/* This file contains constants defined in <linux/errqueue.h> and
* <linux/net_tstamp.h> so as to allow collecting network timestamps in the
* kernel. This file allows tcp_posix.cc to compile on platforms that do not
* have <linux/errqueue.h> and <linux/net_tstamp.h>.
*/
#ifndef GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H
#define GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET_TCP
#include <sys/types.h>
#include <time.h>
#ifdef GRPC_LINUX_ERRQUEUE
#include <linux/errqueue.h>
#include <linux/net_tstamp.h>
#include <sys/socket.h>
#endif /* GRPC_LINUX_ERRQUEUE */
namespace grpc_core {
#ifdef GRPC_LINUX_ERRQUEUE
constexpr uint32_t kTimestampingSocketOptions = SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_ID |
SOF_TIMESTAMPING_OPT_TSONLY;
constexpr uint32_t kTimestampingRecordingOptions =
SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_ACK;
#endif /* GRPC_LINUX_ERRQUEUE */
/* Returns true if kernel is capable of supporting errqueue and timestamping.
* Currently allowing only linux kernels above 4.0.0
*/
bool kernel_supports_errqueue();
} // namespace grpc_core
#endif /* GRPC_POSIX_SOCKET_TCP */
#endif /* GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H */

@ -60,6 +60,12 @@
#define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1
#define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_MSG_NOSIGNAL 1
#define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_HAVE_UNIX_SOCKET 1
#include <linux/version.h>
#ifdef LINUX_VERSION_CODE
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
#define GRPC_LINUX_ERRQUEUE 1
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */
#endif /* LINUX_VERSION_CODE */
#define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1
#define GRPC_POSIX_FORK 1 #define GRPC_POSIX_FORK 1
#define GRPC_POSIX_HOST_NAME_MAX 1 #define GRPC_POSIX_HOST_NAME_MAX 1

@ -279,7 +279,7 @@ grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args,
} }
addr_str = grpc_sockaddr_to_uri(mapped_addr); addr_str = grpc_sockaddr_to_uri(mapped_addr);
gpr_asprintf(&name, "tcp-client:%s", addr_str); gpr_asprintf(&name, "tcp-client:%s", addr_str);
*fdobj = grpc_fd_create(fd, name, false); *fdobj = grpc_fd_create(fd, name, true);
gpr_free(name); gpr_free(name);
gpr_free(addr_str); gpr_free(addr_str);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -221,7 +221,7 @@ static void custom_write_callback(grpc_custom_socket* socket,
} }
static void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* write_slices, static void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* write_slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep; custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep;
GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();

@ -27,7 +27,9 @@
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <netinet/in.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -46,6 +48,7 @@
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/buffer_list.h"
#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
@ -97,17 +100,42 @@ struct grpc_tcp {
grpc_closure read_done_closure; grpc_closure read_done_closure;
grpc_closure write_done_closure; grpc_closure write_done_closure;
grpc_closure error_closure;
char* peer_string; char* peer_string;
grpc_resource_user* resource_user; grpc_resource_user* resource_user;
grpc_resource_user_slice_allocator slice_allocator; grpc_resource_user_slice_allocator slice_allocator;
grpc_core::TracedBuffer* tb_head; /* List of traced buffers */
gpr_mu tb_mu; /* Lock for access to list of traced buffers */
/* grpc_endpoint_write takes an argument which if non-null means that the
* transport layer wants the TCP layer to collect timestamps for this write.
* This arg is forwarded to the timestamps callback function when the ACK
* timestamp is received from the kernel. This arg is a (void *) which allows
* users of this API to pass in a pointer to any kind of structure. This
* structure could actually be a tag or any book-keeping object that the user
* can use to distinguish between different traced writes. The only
* requirement from the TCP endpoint layer is that this arg should be non-null
* if the user wants timestamps for the write. */
void* outgoing_buffer_arg;
/* A counter which starts at 0. It is initialized the first time the socket
* options for collecting timestamps are set, and is incremented with each
* byte sent. */
int bytes_counter;
bool socket_ts_enabled; /* True if timestamping options are set on the socket
*/
gpr_atm
stop_error_notification; /* Set to 1 if we do not want to be notified on
errors anymore */
}; };
struct backup_poller { struct backup_poller {
gpr_mu* pollset_mu; gpr_mu* pollset_mu;
grpc_closure run_poller; grpc_closure run_poller;
}; };
} // namespace } // namespace
#define BACKUP_POLLER_POLLSET(b) ((grpc_pollset*)((b) + 1)) #define BACKUP_POLLER_POLLSET(b) ((grpc_pollset*)((b) + 1))
@ -302,6 +330,7 @@ static void tcp_free(grpc_tcp* tcp) {
grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer);
grpc_resource_user_unref(tcp->resource_user); grpc_resource_user_unref(tcp->resource_user);
gpr_free(tcp->peer_string); gpr_free(tcp->peer_string);
gpr_mu_destroy(&tcp->tb_mu);
gpr_free(tcp); gpr_free(tcp);
} }
@ -347,6 +376,10 @@ static void tcp_destroy(grpc_endpoint* ep) {
grpc_network_status_unregister_endpoint(ep); grpc_network_status_unregister_endpoint(ep);
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep); grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep);
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
if (grpc_event_engine_can_track_errors()) {
gpr_atm_no_barrier_store(&tcp->stop_error_notification, true);
grpc_fd_set_error(tcp->em_fd);
}
TCP_UNREF(tcp, "destroy"); TCP_UNREF(tcp, "destroy");
} }
@ -513,6 +546,234 @@ static void tcp_read(grpc_endpoint* ep, grpc_slice_buffer* incoming_buffer,
} }
} }
/* A wrapper around sendmsg. It sends \a msg over \a fd and returns the number
* of bytes sent. */
ssize_t tcp_send(int fd, const struct msghdr* msg) {
GPR_TIMER_SCOPE("sendmsg", 1);
ssize_t sent_length;
do {
/* TODO(klempner): Cork if this is a partial write */
GRPC_STATS_INC_SYSCALL_WRITE();
sent_length = sendmsg(fd, msg, SENDMSG_FLAGS);
} while (sent_length < 0 && errno == EINTR);
return sent_length;
}
/** This is to be called if outgoing_buffer_arg is not null. On linux platforms,
* this will call sendmsg with socket options set to collect timestamps inside
* the kernel. On return, sent_length is set to the return value of the sendmsg
* call. Returns false if setting the socket options failed. This is not
* implemented for non-linux platforms currently, and crashes out.
*/
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
size_t sending_length,
ssize_t* sent_length, grpc_error** error);
/** The callback function to be invoked when we get an error on the socket. */
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error);
#ifdef GRPC_LINUX_ERRQUEUE
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
size_t sending_length,
ssize_t* sent_length,
grpc_error** error) {
if (!tcp->socket_ts_enabled) {
uint32_t opt = grpc_core::kTimestampingSocketOptions;
if (setsockopt(tcp->fd, SOL_SOCKET, SO_TIMESTAMPING,
static_cast<void*>(&opt), sizeof(opt)) != 0) {
*error = tcp_annotate_error(GRPC_OS_ERROR(errno, "setsockopt"), tcp);
grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_ERROR, "Failed to set timestamping options on the socket.");
}
return false;
}
tcp->bytes_counter = -1;
tcp->socket_ts_enabled = true;
}
/* Set control message to indicate that you want timestamps. */
union {
char cmsg_buf[CMSG_SPACE(sizeof(uint32_t))];
struct cmsghdr align;
} u;
cmsghdr* cmsg = reinterpret_cast<cmsghdr*>(u.cmsg_buf);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SO_TIMESTAMPING;
cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
*reinterpret_cast<int*>(CMSG_DATA(cmsg)) =
grpc_core::kTimestampingRecordingOptions;
msg->msg_control = u.cmsg_buf;
msg->msg_controllen = CMSG_SPACE(sizeof(uint32_t));
/* If there was an error on sendmsg the logic in tcp_flush will handle it. */
ssize_t length = tcp_send(tcp->fd, msg);
*sent_length = length;
/* Only save timestamps if all the bytes were taken by sendmsg. */
if (sending_length == static_cast<size_t>(length)) {
gpr_mu_lock(&tcp->tb_mu);
grpc_core::TracedBuffer::AddNewEntry(
&tcp->tb_head, static_cast<int>(tcp->bytes_counter + length),
tcp->outgoing_buffer_arg);
gpr_mu_unlock(&tcp->tb_mu);
tcp->outgoing_buffer_arg = nullptr;
}
return true;
}
/** Reads \a cmsg to derive timestamps from the control messages. If a valid
* timestamp is found, the traced buffer list is updated with this timestamp.
* The caller of this function should be looping on the control messages found
* in \a msg. \a cmsg should point to the control message that the caller wants
* processed.
* On return, a pointer to a control message is returned. On the next iteration,
* CMSG_NXTHDR(msg, ret_val) should be passed as \a cmsg. */
struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
struct cmsghdr* cmsg) {
auto next_cmsg = CMSG_NXTHDR(msg, cmsg);
if (next_cmsg == nullptr) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_ERROR, "Received timestamp without extended error");
}
return cmsg;
}
if (!(next_cmsg->cmsg_level == SOL_IP || next_cmsg->cmsg_level == SOL_IPV6) ||
!(next_cmsg->cmsg_type == IP_RECVERR ||
next_cmsg->cmsg_type == IPV6_RECVERR)) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_ERROR, "Unexpected control message");
}
return cmsg;
}
auto tss = reinterpret_cast<struct scm_timestamping*>(CMSG_DATA(cmsg));
auto serr = reinterpret_cast<struct sock_extended_err*>(CMSG_DATA(next_cmsg));
if (serr->ee_errno != ENOMSG ||
serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
gpr_log(GPR_ERROR, "Unexpected control message");
return cmsg;
}
/* The error handling can potentially be done on another thread so we need
* to protect the traced buffer list. A lock free list might be better. Using
* a simple mutex for now. */
gpr_mu_lock(&tcp->tb_mu);
grpc_core::TracedBuffer::ProcessTimestamp(&tcp->tb_head, serr, tss);
gpr_mu_unlock(&tcp->tb_mu);
return next_cmsg;
}
/** For linux platforms, reads the socket's error queue and processes error
* messages from the queue. Returns true if all the errors processed were
* timestamps. Returns false if any of the errors were not timestamps. For
* non-linux platforms, error processing is not used/enabled currently.
*/
static bool process_errors(grpc_tcp* tcp) {
while (true) {
struct iovec iov;
iov.iov_base = nullptr;
iov.iov_len = 0;
struct msghdr msg;
msg.msg_name = nullptr;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 0;
msg.msg_flags = 0;
union {
char rbuf[1024 /*CMSG_SPACE(sizeof(scm_timestamping)) +
CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in))*/];
struct cmsghdr align;
} aligned_buf;
memset(&aligned_buf, 0, sizeof(aligned_buf));
msg.msg_control = aligned_buf.rbuf;
msg.msg_controllen = sizeof(aligned_buf.rbuf);
int r, saved_errno;
do {
r = recvmsg(tcp->fd, &msg, MSG_ERRQUEUE);
saved_errno = errno;
} while (r < 0 && saved_errno == EINTR);
if (r == -1 && saved_errno == EAGAIN) {
return true; /* No more errors to process */
}
if (r == -1) {
return false;
}
if (grpc_tcp_trace.enabled()) {
if ((msg.msg_flags & MSG_CTRUNC) == 1) {
gpr_log(GPR_INFO, "Error message was truncated.");
}
}
if (msg.msg_controllen == 0) {
/* There was no control message found. It was probably spurious. */
return true;
}
for (auto cmsg = CMSG_FIRSTHDR(&msg); cmsg && cmsg->cmsg_len;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_TIMESTAMPING) {
/* Got a control message that is not a timestamp. Don't know how to
* handle this. */
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO,
"unknown control message cmsg_level:%d cmsg_type:%d",
cmsg->cmsg_level, cmsg->cmsg_type);
}
return false;
}
process_timestamp(tcp, &msg, cmsg);
}
}
}
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) {
grpc_tcp* tcp = static_cast<grpc_tcp*>(arg);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, grpc_error_string(error));
}
if (error != GRPC_ERROR_NONE ||
static_cast<bool>(gpr_atm_acq_load(&tcp->stop_error_notification))) {
/* We aren't going to register to hear on error anymore, so it is safe to
* unref. */
grpc_core::TracedBuffer::Shutdown(&tcp->tb_head, GRPC_ERROR_REF(error));
TCP_UNREF(tcp, "error-tracking");
return;
}
/* We are still interested in collecting timestamps, so let's try reading
* them. */
if (!process_errors(tcp)) {
/* This was not a timestamps error. This was an actual error. Set the
* read and write closures to be ready.
*/
grpc_fd_set_readable(tcp->em_fd);
grpc_fd_set_writable(tcp->em_fd);
}
GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp,
grpc_schedule_on_exec_ctx);
grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure);
}
#else /* GRPC_LINUX_ERRQUEUE */
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
size_t sending_length,
ssize_t* sent_length,
grpc_error** error) {
gpr_log(GPR_ERROR, "Write with timestamps not supported for this platform");
GPR_ASSERT(0);
return false;
}
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) {
gpr_log(GPR_ERROR, "Error handling is not supported for this platform");
GPR_ASSERT(0);
}
#endif /* GRPC_LINUX_ERRQUEUE */
/* returns true if done, false if pending; if returning true, *error is set */ /* returns true if done, false if pending; if returning true, *error is set */
#if defined(IOV_MAX) && IOV_MAX < 1000 #if defined(IOV_MAX) && IOV_MAX < 1000
#define MAX_WRITE_IOVEC IOV_MAX #define MAX_WRITE_IOVEC IOV_MAX
@ -557,19 +818,20 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) {
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_iov = iov; msg.msg_iov = iov;
msg.msg_iovlen = iov_size; msg.msg_iovlen = iov_size;
msg.msg_control = nullptr;
msg.msg_controllen = 0;
msg.msg_flags = 0; msg.msg_flags = 0;
if (tcp->outgoing_buffer_arg != nullptr) {
if (!tcp_write_with_timestamps(tcp, &msg, sending_length, &sent_length,
error))
return true; /* something went wrong with timestamps */
} else {
msg.msg_control = nullptr;
msg.msg_controllen = 0;
GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length); GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length);
GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size); GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size);
GPR_TIMER_SCOPE("sendmsg", 1); sent_length = tcp_send(tcp->fd, &msg);
do { }
/* TODO(klempner): Cork if this is a partial write */
GRPC_STATS_INC_SYSCALL_WRITE();
sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS);
} while (sent_length < 0 && errno == EINTR);
if (sent_length < 0) { if (sent_length < 0) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
@ -593,6 +855,7 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) {
} }
GPR_ASSERT(tcp->outgoing_byte_idx == 0); GPR_ASSERT(tcp->outgoing_byte_idx == 0);
tcp->bytes_counter += sent_length;
trailing = sending_length - static_cast<size_t>(sent_length); trailing = sending_length - static_cast<size_t>(sent_length);
while (trailing > 0) { while (trailing > 0) {
size_t slice_length; size_t slice_length;
@ -607,7 +870,6 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) {
trailing -= slice_length; trailing -= slice_length;
} }
} }
if (outgoing_slice_idx == tcp->outgoing_buffer->count) { if (outgoing_slice_idx == tcp->outgoing_buffer->count) {
*error = GRPC_ERROR_NONE; *error = GRPC_ERROR_NONE;
grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer);
@ -640,14 +902,13 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) {
const char* str = grpc_error_string(error); const char* str = grpc_error_string(error);
gpr_log(GPR_INFO, "write: %s", str); gpr_log(GPR_INFO, "write: %s", str);
} }
GRPC_CLOSURE_SCHED(cb, error); GRPC_CLOSURE_SCHED(cb, error);
TCP_UNREF(tcp, "write"); TCP_UNREF(tcp, "write");
} }
} }
static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
GPR_TIMER_SCOPE("tcp_write", 0); GPR_TIMER_SCOPE("tcp_write", 0);
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep); grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep);
grpc_error* error = GRPC_ERROR_NONE; grpc_error* error = GRPC_ERROR_NONE;
@ -675,6 +936,10 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
} }
tcp->outgoing_buffer = buf; tcp->outgoing_buffer = buf;
tcp->outgoing_byte_idx = 0; tcp->outgoing_byte_idx = 0;
tcp->outgoing_buffer_arg = arg;
if (arg) {
GPR_ASSERT(grpc_event_engine_can_track_errors());
}
if (!tcp_flush(tcp, &error)) { if (!tcp_flush(tcp, &error)) {
TCP_REF(tcp, "write"); TCP_REF(tcp, "write");
@ -792,6 +1057,8 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
tcp->bytes_read_this_round = 0; tcp->bytes_read_this_round = 0;
/* Will be set to false by the very first endpoint read function */ /* Will be set to false by the very first endpoint read function */
tcp->is_first_read = true; tcp->is_first_read = true;
tcp->bytes_counter = -1;
tcp->socket_ts_enabled = false;
/* paired with unref in grpc_tcp_destroy */ /* paired with unref in grpc_tcp_destroy */
gpr_ref_init(&tcp->refcount, 1); gpr_ref_init(&tcp->refcount, 1);
gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); gpr_atm_no_barrier_store(&tcp->shutdown_count, 0);
@ -803,6 +1070,19 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
/* Tell network status tracker about new endpoint */ /* Tell network status tracker about new endpoint */
grpc_network_status_register_endpoint(&tcp->base); grpc_network_status_register_endpoint(&tcp->base);
grpc_resource_quota_unref_internal(resource_quota); grpc_resource_quota_unref_internal(resource_quota);
gpr_mu_init(&tcp->tb_mu);
tcp->tb_head = nullptr;
/* Start being notified on errors if event engine can track errors. */
if (grpc_event_engine_can_track_errors()) {
/* Grab a ref to tcp so that we can safely access the tcp struct when
* processing errors. We unref when we no longer want to track errors
* separately. */
TCP_REF(tcp, "error-tracking");
gpr_atm_rel_store(&tcp->stop_error_notification, 0);
GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp,
grpc_schedule_on_exec_ctx);
grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure);
}
return &tcp->base; return &tcp->base;
} }
@ -821,6 +1101,11 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd,
tcp->release_fd = fd; tcp->release_fd = fd;
tcp->release_fd_cb = done; tcp->release_fd_cb = done;
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
if (grpc_event_engine_can_track_errors()) {
/* Stop errors notification. */
gpr_atm_no_barrier_store(&tcp->stop_error_notification, true);
grpc_fd_set_error(tcp->em_fd);
}
TCP_UNREF(tcp, "destroy"); TCP_UNREF(tcp, "destroy");
} }

@ -31,7 +31,10 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/buffer_list.h"
#include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/ev_posix.h"

@ -226,7 +226,7 @@ static void on_read(void* arg, grpc_error* err) {
gpr_log(GPR_INFO, "SERVER_CONNECT: incoming connection: %s", addr_str); gpr_log(GPR_INFO, "SERVER_CONNECT: incoming connection: %s", addr_str);
} }
grpc_fd* fdobj = grpc_fd_create(fd, name, false); grpc_fd* fdobj = grpc_fd_create(fd, name, true);
read_notifier_pollset = read_notifier_pollset =
sp->server->pollsets[static_cast<size_t>(gpr_atm_no_barrier_fetch_add( sp->server->pollsets[static_cast<size_t>(gpr_atm_no_barrier_fetch_add(
@ -362,7 +362,7 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) {
listener->sibling = sp; listener->sibling = sp;
sp->server = listener->server; sp->server = listener->server;
sp->fd = fd; sp->fd = fd;
sp->emfd = grpc_fd_create(fd, name, false); sp->emfd = grpc_fd_create(fd, name, true);
memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address)); memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address));
sp->port = port; sp->port = port;
sp->port_index = listener->port_index; sp->port_index = listener->port_index;

@ -105,7 +105,7 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd,
s->tail = sp; s->tail = sp;
sp->server = s; sp->server = s;
sp->fd = fd; sp->fd = fd;
sp->emfd = grpc_fd_create(fd, name, false); sp->emfd = grpc_fd_create(fd, name, true);
memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
sp->port = port; sp->port = port;
sp->port_index = port_index; sp->port_index = port_index;

@ -296,7 +296,7 @@ static void on_write(void* tcpp, grpc_error* error) {
/* Initiates a write. */ /* Initiates a write. */
static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
grpc_tcp* tcp = (grpc_tcp*)ep; grpc_tcp* tcp = (grpc_tcp*)ep;
grpc_winsocket* socket = tcp->socket; grpc_winsocket* socket = tcp->socket;
grpc_winsocket_callback_info* info = &socket->write_info; grpc_winsocket_callback_info* info = &socket->write_info;

@ -152,7 +152,7 @@ GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd,
grpc_sockaddr_to_string(&addr_str, addr, 1); grpc_sockaddr_to_string(&addr_str, addr, 1);
gpr_asprintf(&name, "udp-server-listener:%s", addr_str); gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
gpr_free(addr_str); gpr_free(addr_str);
emfd_ = grpc_fd_create(fd, name, false); emfd_ = grpc_fd_create(fd, name, true);
memcpy(&addr_, addr, sizeof(grpc_resolved_address)); memcpy(&addr_, addr, sizeof(grpc_resolved_address));
GPR_ASSERT(emfd_); GPR_ASSERT(emfd_);
gpr_free(name); gpr_free(name);

@ -254,7 +254,7 @@ static void flush_write_staging_buffer(secure_endpoint* ep, uint8_t** cur,
} }
static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
GPR_TIMER_SCOPE("secure_endpoint.endpoint_write", 0); GPR_TIMER_SCOPE("secure_endpoint.endpoint_write", 0);
unsigned i; unsigned i;
@ -342,7 +342,7 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices,
return; return;
} }
grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb); grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb, arg);
} }
static void endpoint_shutdown(grpc_endpoint* secure_ep, grpc_error* why) { static void endpoint_shutdown(grpc_endpoint* secure_ep, grpc_error* why) {

@ -259,7 +259,7 @@ static grpc_error* on_handshake_next_done_locked(
grpc_slice_buffer_reset_and_unref_internal(&h->outgoing); grpc_slice_buffer_reset_and_unref_internal(&h->outgoing);
grpc_slice_buffer_add(&h->outgoing, to_send); grpc_slice_buffer_add(&h->outgoing, to_send);
grpc_endpoint_write(h->args->endpoint, &h->outgoing, grpc_endpoint_write(h->args->endpoint, &h->outgoing,
&h->on_handshake_data_sent_to_peer); &h->on_handshake_data_sent_to_peer, nullptr);
} else if (handshaker_result == nullptr) { } else if (handshaker_result == nullptr) {
// There is nothing to send, but need to read from peer. // There is nothing to send, but need to read from peer.
grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, grpc_endpoint_read(h->args->endpoint, h->args->read_buffer,

@ -37,8 +37,6 @@ _GRPC_ENABLE_FORK_SUPPORT = (
os.environ.get('GRPC_ENABLE_FORK_SUPPORT', '0') os.environ.get('GRPC_ENABLE_FORK_SUPPORT', '0')
.lower() in _TRUE_VALUES) .lower() in _TRUE_VALUES)
_GRPC_POLL_STRATEGY = os.environ.get('GRPC_POLL_STRATEGY')
cdef void __prefork() nogil: cdef void __prefork() nogil:
with gil: with gil:
with _fork_state.fork_in_progress_condition: with _fork_state.fork_in_progress_condition:
@ -82,13 +80,6 @@ cdef void __postfork_child() nogil:
def fork_handlers_and_grpc_init(): def fork_handlers_and_grpc_init():
grpc_init() grpc_init()
if _GRPC_ENABLE_FORK_SUPPORT: if _GRPC_ENABLE_FORK_SUPPORT:
# TODO(ericgribkoff) epoll1 is default for grpcio distribution. Decide whether to expose
# grpc_get_poll_strategy_name() from ev_posix.cc to get actual polling choice.
if _GRPC_POLL_STRATEGY is not None and _GRPC_POLL_STRATEGY != "epoll1":
_LOGGER.error(
'gRPC Python fork support is only compatible with the epoll1 '
'polling engine')
return
with _fork_state.fork_handler_registered_lock: with _fork_state.fork_handler_registered_lock:
if not _fork_state.fork_handler_registered: if not _fork_state.fork_handler_registered:
pthread_atfork(&__prefork, &__postfork_parent, &__postfork_child) pthread_atfork(&__prefork, &__postfork_parent, &__postfork_child)

@ -82,6 +82,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/http/format_request.cc', 'src/core/lib/http/format_request.cc',
'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli.cc',
'src/core/lib/http/parser.cc', 'src/core/lib/http/parser.cc',
'src/core/lib/iomgr/buffer_list.cc',
'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/call_combiner.cc',
'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/combiner.cc',
'src/core/lib/iomgr/endpoint.cc', 'src/core/lib/iomgr/endpoint.cc',
@ -102,6 +103,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_fallback.cc',
'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc',
'src/core/lib/iomgr/gethostname_sysconf.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc',
'src/core/lib/iomgr/internal_errqueue.cc',
'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iocp_windows.cc',
'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr.cc',
'src/core/lib/iomgr/iomgr_custom.cc', 'src/core/lib/iomgr/iomgr_custom.cc',

@ -115,7 +115,7 @@ void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
/* Write data */ /* Write data */
grpc_endpoint_write(sfd->client, &outgoing, &done_write_closure); grpc_endpoint_write(sfd->client, &outgoing, &done_write_closure, nullptr);
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
/* Await completion, unless the request is large and write may not finish /* Await completion, unless the request is large and write may not finish

@ -123,6 +123,19 @@ grpc_cc_test(
], ],
) )
grpc_cc_test(
name = "inproc_callback_test",
srcs = ["inproc_callback_test.cc"],
language = "C++",
deps = [
':end2end_tests',
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test( grpc_cc_test(
name = "invalid_call_argument_test", name = "invalid_call_argument_test",
srcs = ["invalid_call_argument_test.cc"], srcs = ["invalid_call_argument_test.cc"],

@ -104,7 +104,7 @@ static void handle_write() {
grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer); grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer);
grpc_slice_buffer_add(&state.outgoing_buffer, slice); grpc_slice_buffer_add(&state.outgoing_buffer, slice);
grpc_endpoint_write(state.tcp, &state.outgoing_buffer, &on_write); grpc_endpoint_write(state.tcp, &state.outgoing_buffer, &on_write, nullptr);
} }
static void handle_read(void* arg, grpc_error* error) { static void handle_read(void* arg, grpc_error* error) {

@ -201,7 +201,7 @@ static void on_client_write_done(void* arg, grpc_error* error) {
&conn->client_write_buffer); &conn->client_write_buffer);
conn->client_is_writing = true; conn->client_is_writing = true;
grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer, grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer,
&conn->on_client_write_done); &conn->on_client_write_done, nullptr);
} else { } else {
// No more writes. Unref the connection. // No more writes. Unref the connection.
proxy_connection_unref(conn, "write_done"); proxy_connection_unref(conn, "write_done");
@ -226,7 +226,7 @@ static void on_server_write_done(void* arg, grpc_error* error) {
&conn->server_write_buffer); &conn->server_write_buffer);
conn->server_is_writing = true; conn->server_is_writing = true;
grpc_endpoint_write(conn->server_endpoint, &conn->server_write_buffer, grpc_endpoint_write(conn->server_endpoint, &conn->server_write_buffer,
&conn->on_server_write_done); &conn->on_server_write_done, nullptr);
} else { } else {
// No more writes. Unref the connection. // No more writes. Unref the connection.
proxy_connection_unref(conn, "server_write"); proxy_connection_unref(conn, "server_write");
@ -257,7 +257,7 @@ static void on_client_read_done(void* arg, grpc_error* error) {
proxy_connection_ref(conn, "client_read"); proxy_connection_ref(conn, "client_read");
conn->server_is_writing = true; conn->server_is_writing = true;
grpc_endpoint_write(conn->server_endpoint, &conn->server_write_buffer, grpc_endpoint_write(conn->server_endpoint, &conn->server_write_buffer,
&conn->on_server_write_done); &conn->on_server_write_done, nullptr);
} }
// Read more data. // Read more data.
grpc_endpoint_read(conn->client_endpoint, &conn->client_read_buffer, grpc_endpoint_read(conn->client_endpoint, &conn->client_read_buffer,
@ -288,7 +288,7 @@ static void on_server_read_done(void* arg, grpc_error* error) {
proxy_connection_ref(conn, "server_read"); proxy_connection_ref(conn, "server_read");
conn->client_is_writing = true; conn->client_is_writing = true;
grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer, grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer,
&conn->on_client_write_done); &conn->on_client_write_done, nullptr);
} }
// Read more data. // Read more data.
grpc_endpoint_read(conn->server_endpoint, &conn->server_read_buffer, grpc_endpoint_read(conn->server_endpoint, &conn->server_read_buffer,
@ -340,7 +340,7 @@ static void on_server_connect_done(void* arg, grpc_error* error) {
grpc_slice_buffer_add(&conn->client_write_buffer, slice); grpc_slice_buffer_add(&conn->client_write_buffer, slice);
conn->client_is_writing = true; conn->client_is_writing = true;
grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer, grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer,
&conn->on_write_response_done); &conn->on_write_response_done, nullptr);
} }
/** /**

@ -0,0 +1,498 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include "src/core/ext/transport/inproc/inproc_transport.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/server.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
typedef struct inproc_fixture_data {
bool dummy; // reserved for future expansion. Struct can't be empty
} inproc_fixture_data;
namespace {
template <typename F>
class CQDeletingCallback : public grpc_core::CQCallbackInterface {
public:
explicit CQDeletingCallback(F f) : func_(f) {}
~CQDeletingCallback() override {}
void Run(bool ok) override {
func_(ok);
grpc_core::Delete(this);
}
private:
F func_;
};
template <typename F>
grpc_core::CQCallbackInterface* NewDeletingCallback(F f) {
return grpc_core::New<CQDeletingCallback<F>>(f);
}
class ShutdownCallback : public grpc_core::CQCallbackInterface {
public:
ShutdownCallback() : done_(false) {
gpr_mu_init(&mu_);
gpr_cv_init(&cv_);
}
~ShutdownCallback() override {}
void Run(bool ok) override {
gpr_log(GPR_DEBUG, "CQ shutdown notification invoked");
gpr_mu_lock(&mu_);
done_ = true;
gpr_cv_broadcast(&cv_);
gpr_mu_unlock(&mu_);
}
// The Wait function waits for a specified amount of
// time for the completion of the shutdown and returns
// whether it was successfully shut down
bool Wait(gpr_timespec deadline) {
gpr_mu_lock(&mu_);
while (!done_ && !gpr_cv_wait(&cv_, &mu_, deadline)) {
}
bool ret = done_;
gpr_mu_unlock(&mu_);
return ret;
}
private:
bool done_;
gpr_mu mu_;
gpr_cv cv_;
};
ShutdownCallback* g_shutdown_callback;
} // namespace
// The following global structure is the tag collection. It holds
// all information related to tags expected and tags received
// during the execution, with each callback setting a tag.
// The tag sets are implemented and checked using arrays and
// linear lookups (rather than maps) so that this test doesn't
// need the C++ standard library.
static gpr_mu tags_mu;
static gpr_cv tags_cv;
const size_t kAvailableTags = 4;
bool tags[kAvailableTags];
bool tags_valid[kAvailableTags];
bool tags_expected[kAvailableTags];
bool tags_needed[kAvailableTags];
// Mark that a tag is expected; this function must be executed in the
// main thread only while there are no other threads altering the
// expectation set (e.g., by calling expect_tag or verify_tags)
static void expect_tag(intptr_t tag, bool ok) {
size_t idx = static_cast<size_t>(tag);
GPR_ASSERT(idx < kAvailableTags);
tags_needed[idx] = true;
tags_expected[idx] = ok;
}
// Check that the expected tags have reached, within a certain
// deadline. This must also be executed only on the main thread while
// there are no other threads altering the expectation set (e.g., by
// calling expect_tag or verify_tags). The tag verifier doesn't have
// to drive the CQ at all (unlike the next-based end2end tests)
// because the tags will get set when the callbacks are executed,
// which happens when a particular batch related to a callback is
// complete.
static void verify_tags(gpr_timespec deadline) {
bool done = false;
gpr_mu_lock(&tags_mu);
while (!done) {
done = gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) > 0;
for (size_t i = 0; i < kAvailableTags; i++) {
if (tags_needed[i]) {
if (tags_valid[i]) {
gpr_log(GPR_DEBUG, "Verifying tag %d", static_cast<int>(i));
if (tags[i] != tags_expected[i]) {
gpr_log(GPR_ERROR, "Got wrong result (%d instead of %d) for tag %d",
tags[i], tags_expected[i], static_cast<int>(i));
GPR_ASSERT(false);
}
tags_valid[i] = false;
tags_needed[i] = false;
} else if (done) {
gpr_log(GPR_ERROR, "Didn't get tag %d", static_cast<int>(i));
GPR_ASSERT(false);
}
}
}
bool empty = true;
for (size_t i = 0; i < kAvailableTags; i++) {
if (tags_needed[i]) {
empty = false;
}
}
done = done || empty;
if (done) {
for (size_t i = 0; i < kAvailableTags; i++) {
if (tags_valid[i]) {
gpr_log(GPR_ERROR, "Got unexpected tag %d and result %d",
static_cast<int>(i), tags[i]);
GPR_ASSERT(false);
}
tags_valid[i] = false;
}
} else {
gpr_cv_wait(&tags_cv, &tags_mu, deadline);
}
}
gpr_mu_unlock(&tags_mu);
}
// This function creates a callback functor that emits the
// desired tag into the global tag set
static grpc_core::CQCallbackInterface* tag(intptr_t t) {
auto func = [t](bool ok) {
gpr_mu_lock(&tags_mu);
gpr_log(GPR_DEBUG, "Completing operation %" PRIdPTR, t);
bool was_empty = true;
for (size_t i = 0; i < kAvailableTags; i++) {
if (tags_valid[i]) {
was_empty = false;
}
}
size_t idx = static_cast<size_t>(t);
tags[idx] = ok;
tags_valid[idx] = true;
if (was_empty) {
gpr_cv_signal(&tags_cv);
}
gpr_mu_unlock(&tags_mu);
};
auto cb = NewDeletingCallback(func);
return cb;
}
static grpc_end2end_test_fixture inproc_create_fixture(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
grpc_end2end_test_fixture f;
inproc_fixture_data* ffd = static_cast<inproc_fixture_data*>(
gpr_malloc(sizeof(inproc_fixture_data)));
memset(&f, 0, sizeof(f));
f.fixture_data = ffd;
g_shutdown_callback = grpc_core::New<ShutdownCallback>();
f.cq =
grpc_completion_queue_create_for_callback(g_shutdown_callback, nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
return f;
}
void inproc_init_client(grpc_end2end_test_fixture* f,
grpc_channel_args* client_args) {
f->client = grpc_inproc_channel_create(f->server, client_args, nullptr);
GPR_ASSERT(f->client);
}
void inproc_init_server(grpc_end2end_test_fixture* f,
grpc_channel_args* server_args) {
if (f->server) {
grpc_server_destroy(f->server);
}
f->server = grpc_server_create(server_args, nullptr);
grpc_server_register_completion_queue(f->server, f->cq, nullptr);
grpc_server_start(f->server);
}
void inproc_tear_down(grpc_end2end_test_fixture* f) {
inproc_fixture_data* ffd = static_cast<inproc_fixture_data*>(f->fixture_data);
gpr_free(ffd);
}
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char* test_name,
grpc_channel_args* client_args,
grpc_channel_args* server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
return f;
}
static gpr_timespec n_seconds_from_now(int n) {
return grpc_timeout_seconds_to_deadline(n);
}
static gpr_timespec five_seconds_from_now() { return n_seconds_from_now(5); }
static void drain_cq(grpc_completion_queue* cq) {
// Wait for the shutdown callback to arrive, or fail the test
GPR_ASSERT(g_shutdown_callback->Wait(five_seconds_from_now()));
gpr_log(GPR_DEBUG, "CQ shutdown wait complete");
grpc_core::Delete(g_shutdown_callback);
}
static void shutdown_server(grpc_end2end_test_fixture* f) {
if (!f->server) return;
grpc_server_shutdown_and_notify(
f->server, f->shutdown_cq,
reinterpret_cast<void*>(static_cast<intptr_t>(1000)));
GPR_ASSERT(
grpc_completion_queue_pluck(f->shutdown_cq, (void*)((intptr_t)1000),
grpc_timeout_seconds_to_deadline(5), nullptr)
.type == GRPC_OP_COMPLETE);
grpc_server_destroy(f->server);
f->server = nullptr;
}
static void shutdown_client(grpc_end2end_test_fixture* f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = nullptr;
}
static void end_test(grpc_end2end_test_fixture* f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->cq);
drain_cq(f->cq);
grpc_completion_queue_destroy(f->cq);
grpc_completion_queue_destroy(f->shutdown_cq);
}
static void simple_request_body(grpc_end2end_test_config config,
grpc_end2end_test_fixture f) {
grpc_call* c;
grpc_call* s;
grpc_op ops[6];
grpc_op* op;
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_status_code status;
const char* error_string;
grpc_call_error error;
grpc_slice details;
int was_cancelled = 2;
char* peer;
gpr_timespec deadline = five_seconds_from_now();
c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
grpc_slice_from_static_string("/foo"), nullptr,
deadline, nullptr);
GPR_ASSERT(c);
peer = grpc_call_get_peer(c);
GPR_ASSERT(peer != nullptr);
gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
gpr_free(peer);
grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
// Create a basic client unary request batch (no payload)
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = nullptr;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op->flags = 0;
op->reserved = nullptr;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
op->flags = 0;
op->reserved = nullptr;
op++;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
op->data.recv_status_on_client.error_string = &error_string;
op->flags = 0;
op->reserved = nullptr;
op++;
error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
nullptr);
GPR_ASSERT(GRPC_CALL_OK == error);
// Register a call at the server-side to match the incoming client call
error = grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(2));
GPR_ASSERT(GRPC_CALL_OK == error);
// We expect that the server call creation callback (and no others) will
// execute now since no other batch should be complete.
expect_tag(2, true);
verify_tags(deadline);
peer = grpc_call_get_peer(s);
GPR_ASSERT(peer != nullptr);
gpr_log(GPR_DEBUG, "server_peer=%s", peer);
gpr_free(peer);
peer = grpc_call_get_peer(c);
GPR_ASSERT(peer != nullptr);
gpr_log(GPR_DEBUG, "client_peer=%s", peer);
gpr_free(peer);
// Create the server response batch (no payload)
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = nullptr;
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
grpc_slice status_details = grpc_slice_from_static_string("xyz");
op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
op->reserved = nullptr;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op->flags = 0;
op->reserved = nullptr;
op++;
error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(3),
nullptr);
GPR_ASSERT(GRPC_CALL_OK == error);
// Both the client request and server response batches should get complete
// now and we should see that their callbacks have been executed
expect_tag(3, true);
expect_tag(1, true);
verify_tags(deadline);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
// the following sanity check makes sure that the requested error string is
// correctly populated by the core. It looks for certain substrings that are
// not likely to change much. Some parts of the error, like time created,
// obviously are not checked.
GPR_ASSERT(nullptr != strstr(error_string, "xyz"));
GPR_ASSERT(nullptr != strstr(error_string, "description"));
GPR_ASSERT(nullptr != strstr(error_string, "Error received from peer"));
GPR_ASSERT(nullptr != strstr(error_string, "grpc_message"));
GPR_ASSERT(nullptr != strstr(error_string, "grpc_status"));
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
GPR_ASSERT(0 == call_details.flags);
GPR_ASSERT(was_cancelled == 1);
grpc_slice_unref(details);
gpr_free(static_cast<void*>(const_cast<char*>(error_string)));
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
grpc_call_unref(c);
grpc_call_unref(s);
int expected_calls = 1;
if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) {
expected_calls *= 2;
}
}
static void test_invoke_simple_request(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f;
f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
simple_request_body(config, f);
end_test(&f);
config.tear_down_data(&f);
}
static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
int i;
grpc_end2end_test_fixture f =
begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr);
for (i = 0; i < 10; i++) {
simple_request_body(config, f);
gpr_log(GPR_INFO, "Running test: Passed simple request %d", i);
}
end_test(&f);
config.tear_down_data(&f);
}
static void test_invoke_many_simple_requests(grpc_end2end_test_config config) {
int i;
const int many = 1000;
grpc_end2end_test_fixture f =
begin_test(config, "test_invoke_many_simple_requests", nullptr, nullptr);
gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC);
for (i = 0; i < many; i++) {
simple_request_body(config, f);
}
double us =
gpr_timespec_to_micros(gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), t1)) /
many;
gpr_log(GPR_INFO, "Time per ping %f us", us);
end_test(&f);
config.tear_down_data(&f);
}
static void simple_request(grpc_end2end_test_config config) {
int i;
for (i = 0; i < 10; i++) {
test_invoke_simple_request(config);
}
test_invoke_10_simple_requests(config);
test_invoke_many_simple_requests(config);
}
static void simple_request_pre_init() {
gpr_mu_init(&tags_mu);
gpr_cv_init(&tags_cv);
}
/* All test configurations */
static grpc_end2end_test_config configs[] = {
{"inproc-callback", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
inproc_create_fixture, inproc_init_client, inproc_init_server,
inproc_tear_down},
};
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
grpc_init();
simple_request_pre_init();
simple_request(configs[0]);
grpc_shutdown();
return 0;
}

@ -246,6 +246,19 @@ grpc_cc_test(
], ],
) )
grpc_cc_test(
name = "buffer_list_test",
srcs = ["buffer_list_test.cc"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test( grpc_cc_test(
name = "tcp_server_posix_test", name = "tcp_server_posix_test",
srcs = ["tcp_server_posix_test.cc"], srcs = ["tcp_server_posix_test.cc"],

@ -0,0 +1,111 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "src/core/lib/iomgr/port.h"
#include "src/core/lib/iomgr/buffer_list.h"
#include <grpc/grpc.h>
#include "test/core/util/test_config.h"
#ifdef GRPC_LINUX_ERRQUEUE
static void TestShutdownFlushesListVerifier(void* arg,
grpc_core::Timestamps* ts,
grpc_error* error) {
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(arg != nullptr);
gpr_atm* done = reinterpret_cast<gpr_atm*>(arg);
gpr_atm_rel_store(done, static_cast<gpr_atm>(1));
}
/** Tests that all TracedBuffer elements in the list are flushed out on
* shutdown.
* Also tests that arg is passed correctly.
*/
static void TestShutdownFlushesList() {
grpc_core::grpc_tcp_set_write_timestamps_callback(
TestShutdownFlushesListVerifier);
grpc_core::TracedBuffer* list = nullptr;
#define NUM_ELEM 5
gpr_atm verifier_called[NUM_ELEM];
for (auto i = 0; i < NUM_ELEM; i++) {
gpr_atm_rel_store(&verifier_called[i], static_cast<gpr_atm>(0));
grpc_core::TracedBuffer::AddNewEntry(
&list, i, static_cast<void*>(&verifier_called[i]));
}
grpc_core::TracedBuffer::Shutdown(&list, GRPC_ERROR_NONE);
GPR_ASSERT(list == nullptr);
for (auto i = 0; i < NUM_ELEM; i++) {
GPR_ASSERT(gpr_atm_acq_load(&verifier_called[i]) ==
static_cast<gpr_atm>(1));
}
}
static void TestVerifierCalledOnAckVerifier(void* arg,
grpc_core::Timestamps* ts,
grpc_error* error) {
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(arg != nullptr);
GPR_ASSERT(ts->acked_time.clock_type == GPR_CLOCK_REALTIME);
GPR_ASSERT(ts->acked_time.tv_sec == 123);
GPR_ASSERT(ts->acked_time.tv_nsec == 456);
gpr_atm* done = reinterpret_cast<gpr_atm*>(arg);
gpr_atm_rel_store(done, static_cast<gpr_atm>(1));
}
/** Tests that the timestamp verifier is called on an ACK timestamp.
*/
static void TestVerifierCalledOnAck() {
struct sock_extended_err serr;
serr.ee_data = 213;
serr.ee_info = SCM_TSTAMP_ACK;
struct scm_timestamping tss;
tss.ts[0].tv_sec = 123;
tss.ts[0].tv_nsec = 456;
grpc_core::grpc_tcp_set_write_timestamps_callback(
TestVerifierCalledOnAckVerifier);
grpc_core::TracedBuffer* list = nullptr;
gpr_atm verifier_called;
gpr_atm_rel_store(&verifier_called, static_cast<gpr_atm>(0));
grpc_core::TracedBuffer::AddNewEntry(&list, 213, &verifier_called);
grpc_core::TracedBuffer::ProcessTimestamp(&list, &serr, &tss);
GPR_ASSERT(gpr_atm_acq_load(&verifier_called) == static_cast<gpr_atm>(1));
GPR_ASSERT(list == nullptr);
grpc_core::TracedBuffer::Shutdown(&list, GRPC_ERROR_NONE);
}
static void TestTcpBufferList() {
TestVerifierCalledOnAck();
TestShutdownFlushesList();
}
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
grpc_init();
TestTcpBufferList();
grpc_shutdown();
return 0;
}
#else /* GRPC_LINUX_ERRQUEUE */
int main(int argc, char** argv) { return 0; }
#endif /* GRPC_LINUX_ERRQUEUE */

@ -150,8 +150,8 @@ static void read_and_write_test_write_handler(void* data, grpc_error* error) {
&state->current_write_data); &state->current_write_data);
grpc_slice_buffer_reset_and_unref(&state->outgoing); grpc_slice_buffer_reset_and_unref(&state->outgoing);
grpc_slice_buffer_addn(&state->outgoing, slices, nslices); grpc_slice_buffer_addn(&state->outgoing, slices, nslices);
grpc_endpoint_write(state->write_ep, &state->outgoing, grpc_endpoint_write(state->write_ep, &state->outgoing, &state->done_write,
&state->done_write); nullptr);
gpr_free(slices); gpr_free(slices);
return; return;
} }
@ -294,7 +294,8 @@ static void multiple_shutdown_test(grpc_endpoint_test_config config) {
grpc_slice_buffer_add(&slice_buffer, grpc_slice_from_copied_string("a")); grpc_slice_buffer_add(&slice_buffer, grpc_slice_from_copied_string("a"));
grpc_endpoint_write(f.client_ep, &slice_buffer, grpc_endpoint_write(f.client_ep, &slice_buffer,
GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count,
grpc_schedule_on_exec_ctx)); grpc_schedule_on_exec_ctx),
nullptr);
wait_for_fail_count(&fail_count, 3); wait_for_fail_count(&fail_count, 3);
grpc_endpoint_shutdown(f.client_ep, grpc_endpoint_shutdown(f.client_ep,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));

@ -36,6 +36,9 @@
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/buffer_list.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/sockaddr_posix.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "test/core/iomgr/endpoint_tests.h" #include "test/core/iomgr/endpoint_tests.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
@ -68,6 +71,43 @@ static void create_sockets(int sv[2]) {
GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
} }
static void create_inet_sockets(int sv[2]) {
/* Prepare listening socket */
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
int sock = socket(AF_INET, SOCK_STREAM, 0);
GPR_ASSERT(sock);
GPR_ASSERT(bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in)) == 0);
listen(sock, 1);
/* Prepare client socket and connect to server */
socklen_t len = sizeof(sockaddr_in);
GPR_ASSERT(getsockname(sock, (sockaddr*)&addr, &len) == 0);
int client = socket(AF_INET, SOCK_STREAM, 0);
GPR_ASSERT(client);
int ret;
do {
ret = connect(client, (sockaddr*)&addr, sizeof(sockaddr_in));
} while (ret == -1 && errno == EINTR);
/* Accept client connection */
len = sizeof(socklen_t);
int server;
do {
server = accept(sock, (sockaddr*)&addr, (socklen_t*)&len);
} while (server == -1 && errno == EINTR);
GPR_ASSERT(server != -1);
sv[0] = server;
sv[1] = client;
int flags = fcntl(sv[0], F_GETFL, 0);
GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
flags = fcntl(sv[1], F_GETFL, 0);
GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
}
static ssize_t fill_socket(int fd) { static ssize_t fill_socket(int fd) {
ssize_t write_bytes; ssize_t write_bytes;
ssize_t total_bytes = 0; ssize_t total_bytes = 0;
@ -289,11 +329,10 @@ static grpc_slice* allocate_blocks(size_t num_bytes, size_t slice_size,
static void write_done(void* user_data /* write_socket_state */, static void write_done(void* user_data /* write_socket_state */,
grpc_error* error) { grpc_error* error) {
GPR_ASSERT(error == GRPC_ERROR_NONE);
struct write_socket_state* state = struct write_socket_state* state =
static_cast<struct write_socket_state*>(user_data); static_cast<struct write_socket_state*>(user_data);
gpr_log(GPR_INFO, "Write done callback called");
gpr_mu_lock(g_mu); gpr_mu_lock(g_mu);
gpr_log(GPR_INFO, "Signalling write done");
state->write_done = 1; state->write_done = 1;
GPR_ASSERT( GPR_ASSERT(
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, nullptr))); GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, nullptr)));
@ -340,10 +379,24 @@ void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) {
gpr_free(buf); gpr_free(buf);
} }
/* Verifier for timestamps callback for write_test */
void timestamps_verifier(void* arg, grpc_core::Timestamps* ts,
grpc_error* error) {
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(arg != nullptr);
GPR_ASSERT(ts->sendmsg_time.clock_type == GPR_CLOCK_REALTIME);
GPR_ASSERT(ts->scheduled_time.clock_type == GPR_CLOCK_REALTIME);
GPR_ASSERT(ts->acked_time.clock_type == GPR_CLOCK_REALTIME);
gpr_atm* done_timestamps = (gpr_atm*)arg;
gpr_atm_rel_store(done_timestamps, static_cast<gpr_atm>(1));
}
/* Write to a socket using the grpc_tcp API, then drain it directly. /* Write to a socket using the grpc_tcp API, then drain it directly.
Note that if the write does not complete immediately we need to drain the Note that if the write does not complete immediately we need to drain the
socket in parallel with the read. */ socket in parallel with the read. If collect_timestamps is true, it will
static void write_test(size_t num_bytes, size_t slice_size) { try to get timestamps for the write. */
static void write_test(size_t num_bytes, size_t slice_size,
bool collect_timestamps) {
int sv[2]; int sv[2];
grpc_endpoint* ep; grpc_endpoint* ep;
struct write_socket_state state; struct write_socket_state state;
@ -356,19 +409,27 @@ static void write_test(size_t num_bytes, size_t slice_size) {
grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20));
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
if (collect_timestamps && !grpc_event_engine_can_track_errors()) {
return;
}
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"Start write test with %" PRIuPTR " bytes, slice size %" PRIuPTR, "Start write test with %" PRIuPTR " bytes, slice size %" PRIuPTR,
num_bytes, slice_size); num_bytes, slice_size);
create_sockets(sv); if (collect_timestamps) {
create_inet_sockets(sv);
} else {
create_sockets(sv);
}
grpc_arg a[1]; grpc_arg a[1];
a[0].key = const_cast<char*>(GRPC_ARG_TCP_READ_CHUNK_SIZE); a[0].key = const_cast<char*>(GRPC_ARG_TCP_READ_CHUNK_SIZE);
a[0].type = GRPC_ARG_INTEGER, a[0].type = GRPC_ARG_INTEGER,
a[0].value.integer = static_cast<int>(slice_size); a[0].value.integer = static_cast<int>(slice_size);
grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; grpc_channel_args args = {GPR_ARRAY_SIZE(a), a};
ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test", false), &args, ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test", collect_timestamps),
"test"); &args, "test");
grpc_endpoint_add_to_pollset(ep, g_pollset); grpc_endpoint_add_to_pollset(ep, g_pollset);
state.ep = ep; state.ep = ep;
@ -381,18 +442,26 @@ static void write_test(size_t num_bytes, size_t slice_size) {
GRPC_CLOSURE_INIT(&write_done_closure, write_done, &state, GRPC_CLOSURE_INIT(&write_done_closure, write_done, &state,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_endpoint_write(ep, &outgoing, &write_done_closure); gpr_atm done_timestamps;
gpr_atm_rel_store(&done_timestamps, static_cast<gpr_atm>(0));
grpc_endpoint_write(ep, &outgoing, &write_done_closure,
grpc_event_engine_can_track_errors() && collect_timestamps
? (void*)&done_timestamps
: nullptr);
drain_socket_blocking(sv[0], num_bytes, num_bytes); drain_socket_blocking(sv[0], num_bytes, num_bytes);
exec_ctx.Flush();
gpr_mu_lock(g_mu); gpr_mu_lock(g_mu);
for (;;) { for (;;) {
grpc_pollset_worker* worker = nullptr; grpc_pollset_worker* worker = nullptr;
if (state.write_done) { if (state.write_done &&
(!(grpc_event_engine_can_track_errors() && collect_timestamps) ||
gpr_atm_acq_load(&done_timestamps) == static_cast<gpr_atm>(1))) {
break; break;
} }
GPR_ASSERT(GRPC_LOG_IF_ERROR( GPR_ASSERT(GRPC_LOG_IF_ERROR(
"pollset_work", grpc_pollset_work(g_pollset, &worker, deadline))); "pollset_work", grpc_pollset_work(g_pollset, &worker, deadline)));
gpr_mu_unlock(g_mu); gpr_mu_unlock(g_mu);
exec_ctx.Flush();
gpr_mu_lock(g_mu); gpr_mu_lock(g_mu);
} }
gpr_mu_unlock(g_mu); gpr_mu_unlock(g_mu);
@ -497,14 +566,21 @@ void run_tests(void) {
large_read_test(8192); large_read_test(8192);
large_read_test(1); large_read_test(1);
write_test(100, 8192); write_test(100, 8192, false);
write_test(100, 1); write_test(100, 1, false);
write_test(100000, 8192); write_test(100000, 8192, false);
write_test(100000, 1); write_test(100000, 1, false);
write_test(100000, 137); write_test(100000, 137, false);
write_test(100, 8192, true);
write_test(100, 1, true);
write_test(100000, 8192, true);
write_test(100000, 1, true);
write_test(100, 137, true);
for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) {
write_test(40320, i); write_test(40320, i, false);
write_test(40320, i, true);
} }
release_fd_test(100, 8192); release_fd_test(100, 8192);
@ -549,6 +625,7 @@ int main(int argc, char** argv) {
grpc_closure destroyed; grpc_closure destroyed;
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
grpc_init(); grpc_init();
grpc_core::grpc_tcp_set_write_timestamps_callback(timestamps_verifier);
{ {
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
g_pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size())); g_pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));

@ -55,7 +55,7 @@ static void me_read(grpc_endpoint* ep, grpc_slice_buffer* slices,
} }
static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices, static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep); mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
for (size_t i = 0; i < slices->count; i++) { for (size_t i = 0; i < slices->count; i++) {
m->on_write(slices->slices[i]); m->on_write(slices->slices[i]);

@ -76,7 +76,7 @@ static half* other_half(half* h) {
} }
static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices, static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
half* m = other_half(reinterpret_cast<half*>(ep)); half* m = other_half(reinterpret_cast<half*>(ep));
gpr_mu_lock(&m->parent->mu); gpr_mu_lock(&m->parent->mu);
grpc_error* error = GRPC_ERROR_NONE; grpc_error* error = GRPC_ERROR_NONE;

@ -62,7 +62,7 @@ static void maybe_call_write_cb_locked(trickle_endpoint* te) {
} }
static void te_write(grpc_endpoint* ep, grpc_slice_buffer* slices, static void te_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
trickle_endpoint* te = reinterpret_cast<trickle_endpoint*>(ep); trickle_endpoint* te = reinterpret_cast<trickle_endpoint*>(ep);
gpr_mu_lock(&te->mu); gpr_mu_lock(&te->mu);
GPR_ASSERT(te->write_cb == nullptr); GPR_ASSERT(te->write_cb == nullptr);
@ -186,7 +186,8 @@ size_t grpc_trickle_endpoint_trickle(grpc_endpoint* ep) {
te->last_write = now; te->last_write = now;
grpc_endpoint_write( grpc_endpoint_write(
te->wrapped, &te->writing_buffer, te->wrapped, &te->writing_buffer,
GRPC_CLOSURE_CREATE(te_finish_write, te, grpc_schedule_on_exec_ctx)); GRPC_CLOSURE_CREATE(te_finish_write, te, grpc_schedule_on_exec_ctx),
nullptr);
maybe_call_write_cb_locked(te); maybe_call_write_cb_locked(te);
} }
} }

@ -96,7 +96,7 @@ class DummyEndpoint : public grpc_endpoint {
} }
static void write(grpc_endpoint* ep, grpc_slice_buffer* slices, static void write(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) { grpc_closure* cb, void* arg) {
GRPC_CLOSURE_SCHED(cb, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(cb, GRPC_ERROR_NONE);
} }

@ -1067,6 +1067,7 @@ src/core/lib/http/format_request.h \
src/core/lib/http/httpcli.h \ src/core/lib/http/httpcli.h \
src/core/lib/http/parser.h \ src/core/lib/http/parser.h \
src/core/lib/iomgr/block_annotate.h \ src/core/lib/iomgr/block_annotate.h \
src/core/lib/iomgr/buffer_list.h \
src/core/lib/iomgr/call_combiner.h \ src/core/lib/iomgr/call_combiner.h \
src/core/lib/iomgr/closure.h \ src/core/lib/iomgr/closure.h \
src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/combiner.h \
@ -1082,6 +1083,7 @@ src/core/lib/iomgr/ev_posix.h \
src/core/lib/iomgr/exec_ctx.h \ src/core/lib/iomgr/exec_ctx.h \
src/core/lib/iomgr/executor.h \ src/core/lib/iomgr/executor.h \
src/core/lib/iomgr/gethostname.h \ src/core/lib/iomgr/gethostname.h \
src/core/lib/iomgr/internal_errqueue.h \
src/core/lib/iomgr/iocp_windows.h \ src/core/lib/iomgr/iocp_windows.h \
src/core/lib/iomgr/iomgr.h \ src/core/lib/iomgr/iomgr.h \
src/core/lib/iomgr/iomgr_custom.h \ src/core/lib/iomgr/iomgr_custom.h \

@ -1159,6 +1159,8 @@ src/core/lib/http/parser.cc \
src/core/lib/http/parser.h \ src/core/lib/http/parser.h \
src/core/lib/iomgr/README.md \ src/core/lib/iomgr/README.md \
src/core/lib/iomgr/block_annotate.h \ src/core/lib/iomgr/block_annotate.h \
src/core/lib/iomgr/buffer_list.cc \
src/core/lib/iomgr/buffer_list.h \
src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.cc \
src/core/lib/iomgr/call_combiner.h \ src/core/lib/iomgr/call_combiner.h \
src/core/lib/iomgr/closure.h \ src/core/lib/iomgr/closure.h \
@ -1194,6 +1196,8 @@ src/core/lib/iomgr/gethostname.h \
src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_fallback.cc \
src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \
src/core/lib/iomgr/gethostname_sysconf.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \
src/core/lib/iomgr/internal_errqueue.cc \
src/core/lib/iomgr/internal_errqueue.h \
src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.cc \
src/core/lib/iomgr/iocp_windows.h \ src/core/lib/iomgr/iocp_windows.h \
src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr.cc \

@ -163,6 +163,23 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "buffer_list_test",
"src": [
"test/core/iomgr/buffer_list_test.cc"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",
@ -1410,6 +1427,26 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [
"test/core/end2end/end2end_tests.h"
],
"is_filegroup": false,
"language": "c",
"name": "inproc_callback_test",
"src": [
"test/core/end2end/end2end_tests.h",
"test/core/end2end/inproc_callback_test.cc"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",
@ -9468,6 +9505,7 @@
"src/core/lib/http/format_request.cc", "src/core/lib/http/format_request.cc",
"src/core/lib/http/httpcli.cc", "src/core/lib/http/httpcli.cc",
"src/core/lib/http/parser.cc", "src/core/lib/http/parser.cc",
"src/core/lib/iomgr/buffer_list.cc",
"src/core/lib/iomgr/call_combiner.cc", "src/core/lib/iomgr/call_combiner.cc",
"src/core/lib/iomgr/combiner.cc", "src/core/lib/iomgr/combiner.cc",
"src/core/lib/iomgr/endpoint.cc", "src/core/lib/iomgr/endpoint.cc",
@ -9488,6 +9526,7 @@
"src/core/lib/iomgr/gethostname_fallback.cc", "src/core/lib/iomgr/gethostname_fallback.cc",
"src/core/lib/iomgr/gethostname_host_name_max.cc", "src/core/lib/iomgr/gethostname_host_name_max.cc",
"src/core/lib/iomgr/gethostname_sysconf.cc", "src/core/lib/iomgr/gethostname_sysconf.cc",
"src/core/lib/iomgr/internal_errqueue.cc",
"src/core/lib/iomgr/iocp_windows.cc", "src/core/lib/iomgr/iocp_windows.cc",
"src/core/lib/iomgr/iomgr.cc", "src/core/lib/iomgr/iomgr.cc",
"src/core/lib/iomgr/iomgr_custom.cc", "src/core/lib/iomgr/iomgr_custom.cc",
@ -9647,6 +9686,7 @@
"src/core/lib/http/httpcli.h", "src/core/lib/http/httpcli.h",
"src/core/lib/http/parser.h", "src/core/lib/http/parser.h",
"src/core/lib/iomgr/block_annotate.h", "src/core/lib/iomgr/block_annotate.h",
"src/core/lib/iomgr/buffer_list.h",
"src/core/lib/iomgr/call_combiner.h", "src/core/lib/iomgr/call_combiner.h",
"src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/combiner.h",
@ -9662,6 +9702,7 @@
"src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/executor.h",
"src/core/lib/iomgr/gethostname.h", "src/core/lib/iomgr/gethostname.h",
"src/core/lib/iomgr/internal_errqueue.h",
"src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iocp_windows.h",
"src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_custom.h", "src/core/lib/iomgr/iomgr_custom.h",
@ -9797,6 +9838,7 @@
"src/core/lib/http/httpcli.h", "src/core/lib/http/httpcli.h",
"src/core/lib/http/parser.h", "src/core/lib/http/parser.h",
"src/core/lib/iomgr/block_annotate.h", "src/core/lib/iomgr/block_annotate.h",
"src/core/lib/iomgr/buffer_list.h",
"src/core/lib/iomgr/call_combiner.h", "src/core/lib/iomgr/call_combiner.h",
"src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/combiner.h",
@ -9812,6 +9854,7 @@
"src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/executor.h",
"src/core/lib/iomgr/gethostname.h", "src/core/lib/iomgr/gethostname.h",
"src/core/lib/iomgr/internal_errqueue.h",
"src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iocp_windows.h",
"src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_custom.h", "src/core/lib/iomgr/iomgr_custom.h",

@ -195,6 +195,26 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [
"uv"
],
"flaky": false,
"gtest": false,
"language": "c",
"name": "buffer_list_test",
"platforms": [
"linux"
],
"uses_polling": true
},
{ {
"args": [], "args": [],
"benchmark": false, "benchmark": false,
@ -1697,6 +1717,30 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "inproc_callback_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{ {
"args": [], "args": [],
"benchmark": false, "benchmark": false,

Loading…
Cancel
Save