Преглед на файлове

Merge branch 'master' into kerrick-lyft-patch-1

Kerrick Staley преди 7 години
родител
ревизия
f44f0bc592
променени са 70 файла, в които са добавени 1263 реда и са изтрити 184 реда
  1. 8 0
      .gitmodules
  2. 1 0
      BUILD
  3. 3 1
      BUILDING.md
  4. 39 0
      CMakeLists.txt
  5. 3 3
      CONTRIBUTING.md
  6. 109 1
      Makefile
  7. 52 0
      build.yaml
  8. 16 1
      gRPC-C++.podspec
  9. 9 2
      gRPC-Core.podspec
  10. 4 0
      grpc.gemspec
  11. 26 0
      grpc.gyp
  12. 1 0
      include/grpc/module.modulemap
  13. 4 0
      package.xml
  14. 8 2
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
  15. 6 5
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  16. 4 1
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  17. 22 21
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
  18. 4 0
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
  19. 19 6
      src/core/ext/filters/client_channel/subchannel.cc
  20. 22 24
      src/core/lib/channel/channel_stack.cc
  21. 4 1
      src/core/lib/channel/channelz.cc
  22. 28 0
      src/core/lib/gpr/alloc.h
  23. 8 8
      src/core/lib/gpr/arena.cc
  24. 1 1
      src/core/lib/gprpp/thd_posix.cc
  25. 73 24
      src/core/lib/iomgr/ev_epollex_linux.cc
  26. 2 0
      src/core/lib/iomgr/iomgr.cc
  27. 5 0
      src/core/lib/iomgr/iomgr.h
  28. 0 1
      src/core/lib/iomgr/timer_manager.cc
  29. 4 4
      src/core/lib/security/context/security_context.cc
  30. 4 1
      src/core/lib/security/context/security_context.h
  31. 4 5
      src/core/lib/security/transport/server_auth_filter.cc
  32. 6 7
      src/core/lib/surface/call.cc
  33. 2 0
      src/core/lib/surface/call.h
  34. 2 1
      src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
  35. 47 1
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc
  36. 3 1
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h
  37. 12 11
      src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc
  38. 7 2
      src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h
  39. 15 0
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
  40. 15 0
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
  41. 5 0
      src/objective-c/GRPCClient/private/GRPCHost.h
  42. 15 0
      src/objective-c/GRPCClient/private/GRPCHost.m
  43. 92 0
      src/objective-c/NetworkTransitionBehavior.md
  44. 32 0
      src/objective-c/README-CFSTREAM.md
  45. 43 0
      src/objective-c/tests/GRPCClientTests.m
  46. 13 2
      templates/Makefile.template
  47. 9 1
      templates/gRPC-C++.podspec.template
  48. 19 0
      test/build/no-c++14-compat.cc
  49. 19 0
      test/build/no-maybe-uninitialized.c
  50. 19 0
      test/build/no-unused-but-set-variable.c
  51. 18 3
      test/core/iomgr/BUILD
  52. 115 0
      test/core/iomgr/ev_epollex_linux_test.cc
  53. 1 0
      test/core/surface/public_headers_must_be_c89.c
  54. 17 9
      test/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_test.cc
  55. 26 15
      test/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector_test.cc
  56. 35 11
      test/cpp/naming/cancel_ares_query_test.cc
  57. 1 0
      third_party/libcxx
  58. 1 0
      third_party/libcxxabi
  59. 1 0
      tools/doxygen/Doxyfile.c++
  60. 2 0
      tools/doxygen/Doxyfile.c++.internal
  61. 1 0
      tools/doxygen/Doxyfile.core
  62. 4 0
      tools/doxygen/Doxyfile.core.internal
  63. 1 1
      tools/internal_ci/linux/grpc_asan_on_foundry.sh
  64. 2 0
      tools/internal_ci/linux/grpc_ubsan_on_foundry.sh
  65. 19 0
      tools/internal_ci/linux/pull_request/grpc_asan_on_foundry.sh
  66. 68 0
      tools/internal_ci/linux/pull_request/grpc_ubsan_on_foundry.sh
  67. 15 0
      tools/interop_matrix/client_matrix.py
  68. 39 0
      tools/run_tests/generated/sources_and_headers.json
  69. 20 0
      tools/run_tests/generated/tests.json
  70. 9 7
      tools/run_tests/sanity/check_submodules.sh

+ 8 - 0
.gitmodules

@@ -34,3 +34,11 @@
 [submodule "third_party/abseil-cpp"]
 [submodule "third_party/abseil-cpp"]
 	path = third_party/abseil-cpp
 	path = third_party/abseil-cpp
 	url = https://github.com/abseil/abseil-cpp
 	url = https://github.com/abseil/abseil-cpp
+[submodule "third_party/libcxxabi"]
+	path = third_party/libcxxabi
+	url = https://github.com/llvm-mirror/libcxxabi.git
+	branch = release_60
+[submodule "third_party/libcxx"]
+	path = third_party/libcxx
+	url = https://github.com/llvm-mirror/libcxx.git
+	branch = release_60

+ 1 - 0
BUILD

@@ -540,6 +540,7 @@ grpc_cc_library(
         "src/core/lib/profiling/stap_timers.cc",
         "src/core/lib/profiling/stap_timers.cc",
     ],
     ],
     hdrs = [
     hdrs = [
+        "src/core/lib/gpr/alloc.h",
         "src/core/lib/gpr/arena.h",
         "src/core/lib/gpr/arena.h",
         "src/core/lib/gpr/env.h",
         "src/core/lib/gpr/env.h",
         "src/core/lib/gpr/host_port.h",
         "src/core/lib/gpr/host_port.h",

+ 3 - 1
BUILDING.md

@@ -112,9 +112,11 @@ From the grpc repository root
 
 
 ## bazel
 ## bazel
 
 
+See [Installing Bazel](https://docs.bazel.build/versions/master/install.html) for instructions how to install bazel on your system.
+
 From the grpc repository root
 From the grpc repository root
 ```
 ```
-bazel build :all
+$ bazel build :all
 ```
 ```
 
 
 ## cmake: Windows, Using Visual Studio 2015 or 2017 (can only build with OPENSSL_NO_ASM).
 ## cmake: Windows, Using Visual Studio 2015 or 2017 (can only build with OPENSSL_NO_ASM).

+ 39 - 0
CMakeLists.txt

@@ -246,6 +246,9 @@ endif()
 add_dependencies(buildtests_c endpoint_pair_test)
 add_dependencies(buildtests_c endpoint_pair_test)
 add_dependencies(buildtests_c error_test)
 add_dependencies(buildtests_c error_test)
 if(_gRPC_PLATFORM_LINUX)
 if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c ev_epollex_linux_test)
+endif()
+if(_gRPC_PLATFORM_LINUX)
 add_dependencies(buildtests_c ev_epollsig_linux_test)
 add_dependencies(buildtests_c ev_epollsig_linux_test)
 endif()
 endif()
 add_dependencies(buildtests_c fake_resolver_test)
 add_dependencies(buildtests_c fake_resolver_test)
@@ -1301,6 +1304,7 @@ foreach(_hdr
   include/grpc/grpc.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
   include/grpc/status.h
@@ -2603,6 +2607,7 @@ foreach(_hdr
   include/grpc/grpc.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
   include/grpc/status.h
@@ -2919,6 +2924,7 @@ foreach(_hdr
   include/grpc/grpc.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
   include/grpc/status.h
@@ -3482,6 +3488,7 @@ foreach(_hdr
   include/grpc/grpc.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
   include/grpc/status.h
@@ -4381,6 +4388,7 @@ foreach(_hdr
   include/grpc/grpc.h
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
   include/grpc/status.h
@@ -6186,6 +6194,37 @@ endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX)
 if(_gRPC_PLATFORM_LINUX)
 
 
+add_executable(ev_epollex_linux_test
+  test/core/iomgr/ev_epollex_linux_test.cc
+)
+
+
+target_include_directories(ev_epollex_linux_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
+)
+
+target_link_libraries(ev_epollex_linux_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
+
 add_executable(ev_epollsig_linux_test
 add_executable(ev_epollsig_linux_test
   test/core/iomgr/ev_epollsig_linux_test.cc
   test/core/iomgr/ev_epollsig_linux_test.cc
 )
 )

+ 3 - 3
CONTRIBUTING.md

@@ -24,9 +24,9 @@ script that unifies the experience of building and testing gRPC in different
 languages and on different platforms is provided.
 languages and on different platforms is provided.
 
 
 To build gRPC in the language of choice (e.g. `c++`, `csharp`, `php`, `python`, `ruby`, ...)
 To build gRPC in the language of choice (e.g. `c++`, `csharp`, `php`, `python`, `ruby`, ...)
-- Prepare you development environment based on language-specific instructions in `src/YOUR-LANGUAGE` directory.
+- Prepare your development environment based on language-specific instructions in `src/YOUR-LANGUAGE` directory.
 - The language-specific instructions might involve installing C/C++ prerequisites listed in
 - The language-specific instructions might involve installing C/C++ prerequisites listed in
-  [Building gRPC C++: Prerequisites](BUILDING.md#pre-requisites) as gRPC implementations
+  [Building gRPC C++: Prerequisites](BUILDING.md#pre-requisites). This is because gRPC implementations
   in this repository are using the native gRPC "core" library internally.
   in this repository are using the native gRPC "core" library internally.
 - Run
 - Run
   ```
   ```
@@ -38,7 +38,7 @@ To build gRPC in the language of choice (e.g. `c++`, `csharp`, `php`, `python`,
   ```
   ```
 
 
 You can also run `python tools/run_tests/run_tests.py --help` to discover useful command line flags supported. For more details,
 You can also run `python tools/run_tests/run_tests.py --help` to discover useful command line flags supported. For more details,
-see [tools/run_tests](tools/run_tests) where you will also find guidance on how to run various other test suites (e.g. interop tests, benchmarks)
+see [tools/run_tests](tools/run_tests) where you will also find guidance on how to run various other test suites (e.g. interop tests, benchmarks).
 
 
 ## Generated project files
 ## Generated project files
 
 

+ 109 - 1
Makefile

@@ -300,6 +300,12 @@ else
 TMPOUT = `mktemp /tmp/test-out-XXXXXX`
 TMPOUT = `mktemp /tmp/test-out-XXXXXX`
 endif
 endif
 
 
+CHECK_NO_CXX14_COMPAT_WORKS_CMD = $(CC) -std=c++11 -Werror -Wno-c++14-compat -o $(TMPOUT) -c test/build/no-c++14-compat.cc
+HAS_WORKING_NO_CXX14_COMPAT = $(shell $(CHECK_NO_CXX14_COMPAT_WORKS_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_WORKING_NO_CXX14_COMPAT),true)
+W_NO_CXX14_COMPAT=-Wno-c++14-compat
+endif
+
 CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c
 CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c
 HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false)
 HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false)
 ifeq ($(HAS_WORKING_SHADOW),true)
 ifeq ($(HAS_WORKING_SHADOW),true)
@@ -318,6 +324,18 @@ ifeq ($(HAS_WORKING_NO_SHIFT_NEGATIVE_VALUE),true)
 W_NO_SHIFT_NEGATIVE_VALUE=-Wno-shift-negative-value
 W_NO_SHIFT_NEGATIVE_VALUE=-Wno-shift-negative-value
 NO_W_NO_SHIFT_NEGATIVE_VALUE=-Wshift-negative-value
 NO_W_NO_SHIFT_NEGATIVE_VALUE=-Wshift-negative-value
 endif
 endif
+CHECK_NO_UNUSED_BUT_SET_VARIABLE_WORKS_CMD = $(CC) -std=c99 -Werror -Wno-unused-but-set-variable -o $(TMPOUT) -c test/build/no-unused-but-set-variable.c
+HAS_WORKING_NO_UNUSED_BUT_SET_VARIABLE = $(shell $(CHECK_NO_UNUSED_BUT_SET_VARIABLE_WORKS_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_WORKING_NO_UNUSED_BUT_SET_VARIABLE),true)
+W_NO_UNUSED_BUT_SET_VARIABLE=-Wno-unused-but-set-variable
+NO_W_NO_UNUSED_BUT_SET_VARIABLE=-Wunused-but-set-variable
+endif
+CHECK_NO_MAYBE_UNINITIALIZED_WORKS_CMD = $(CC) -std=c99 -Werror -Wno-maybe-uninitialized -o $(TMPOUT) -c test/build/no-maybe-uninitialized.c
+HAS_WORKING_NO_MAYBE_UNINITIALIZED = $(shell $(CHECK_NO_MAYBE_UNINITIALIZED_WORKS_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_WORKING_NO_MAYBE_UNINITIALIZED),true)
+W_NO_MAYBE_UNINITIALIZED=-Wno-maybe-uninitialized
+NO_W_NO_MAYBE_UNINITIALIZED=-Wmaybe-uninitialized
+endif
 
 
 # The HOST compiler settings are used to compile the protoc plugins.
 # The HOST compiler settings are used to compile the protoc plugins.
 # In most cases, you won't have to change anything, but if you are
 # In most cases, you won't have to change anything, but if you are
@@ -968,6 +986,7 @@ dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test
 dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
 dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
 endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
 endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
 error_test: $(BINDIR)/$(CONFIG)/error_test
 error_test: $(BINDIR)/$(CONFIG)/error_test
+ev_epollex_linux_test: $(BINDIR)/$(CONFIG)/ev_epollex_linux_test
 ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
 ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
 fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
 fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
 fake_transport_security_test: $(BINDIR)/$(CONFIG)/fake_transport_security_test
 fake_transport_security_test: $(BINDIR)/$(CONFIG)/fake_transport_security_test
@@ -1371,7 +1390,7 @@ plugins: $(PROTOC_PLUGINS)
 
 
 privatelibs: privatelibs_c privatelibs_cxx
 privatelibs: privatelibs_c privatelibs_cxx
 
 
-privatelibs_c:  $(LIBDIR)/$(CONFIG)/libalts_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a
+privatelibs_c:  $(LIBDIR)/$(CONFIG)/libalts_test_util.a $(LIBDIR)/$(CONFIG)/libcxxabi.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a
 pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc
 pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc
 
 
 pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc
 pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc
@@ -1413,6 +1432,7 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/dualstack_socket_test \
   $(BINDIR)/$(CONFIG)/dualstack_socket_test \
   $(BINDIR)/$(CONFIG)/endpoint_pair_test \
   $(BINDIR)/$(CONFIG)/endpoint_pair_test \
   $(BINDIR)/$(CONFIG)/error_test \
   $(BINDIR)/$(CONFIG)/error_test \
+  $(BINDIR)/$(CONFIG)/ev_epollex_linux_test \
   $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \
   $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \
   $(BINDIR)/$(CONFIG)/fake_resolver_test \
   $(BINDIR)/$(CONFIG)/fake_resolver_test \
   $(BINDIR)/$(CONFIG)/fake_transport_security_test \
   $(BINDIR)/$(CONFIG)/fake_transport_security_test \
@@ -1934,6 +1954,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/endpoint_pair_test || ( echo test endpoint_pair_test failed ; exit 1 )
 	$(Q) $(BINDIR)/$(CONFIG)/endpoint_pair_test || ( echo test endpoint_pair_test failed ; exit 1 )
 	$(E) "[RUN]     Testing error_test"
 	$(E) "[RUN]     Testing error_test"
 	$(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 )
 	$(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 )
+	$(E) "[RUN]     Testing ev_epollex_linux_test"
+	$(Q) $(BINDIR)/$(CONFIG)/ev_epollex_linux_test || ( echo test ev_epollex_linux_test failed ; exit 1 )
 	$(E) "[RUN]     Testing ev_epollsig_linux_test"
 	$(E) "[RUN]     Testing ev_epollsig_linux_test"
 	$(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 )
 	$(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 )
 	$(E) "[RUN]     Testing fake_resolver_test"
 	$(E) "[RUN]     Testing fake_resolver_test"
@@ -2855,6 +2877,11 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc
 	$(Q) mkdir -p `dirname $@`
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
 	$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
 
 
+$(OBJDIR)/$(CONFIG)/%.o : %.cpp
+	$(E) "[CXX]     Compiling $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
+
 install: install_c install_cxx install-plugins install-certs
 install: install_c install_cxx install-plugins install-certs
 
 
 install_c: install-headers_c install-static_c install-shared_c
 install_c: install-headers_c install-static_c install-shared_c
@@ -3169,6 +3196,50 @@ endif
 endif
 endif
 
 
 
 
+LIBCXXABI_SRC = \
+    third_party/libcxxabi/src/abort_message.cpp \
+    third_party/libcxxabi/src/cxa_aux_runtime.cpp \
+    third_party/libcxxabi/src/cxa_default_handlers.cpp \
+    third_party/libcxxabi/src/cxa_demangle.cpp \
+    third_party/libcxxabi/src/cxa_exception_storage.cpp \
+    third_party/libcxxabi/src/cxa_guard.cpp \
+    third_party/libcxxabi/src/cxa_handlers.cpp \
+    third_party/libcxxabi/src/cxa_noexception.cpp \
+    third_party/libcxxabi/src/cxa_thread_atexit.cpp \
+    third_party/libcxxabi/src/cxa_unexpected.cpp \
+    third_party/libcxxabi/src/cxa_vector.cpp \
+    third_party/libcxxabi/src/cxa_virtual.cpp \
+    third_party/libcxxabi/src/fallback_malloc.cpp \
+    third_party/libcxxabi/src/private_typeinfo.cpp \
+    third_party/libcxxabi/src/stdlib_exception.cpp \
+    third_party/libcxxabi/src/stdlib_new_delete.cpp \
+    third_party/libcxxabi/src/stdlib_stdexcept.cpp \
+    third_party/libcxxabi/src/stdlib_typeinfo.cpp \
+
+PUBLIC_HEADERS_C += \
+
+LIBCXXABI_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBCXXABI_SRC))))
+
+$(LIBCXXABI_OBJS): CPPFLAGS += -D_LIBCPP_DISABLE_EXTERN_TEMPLATE -D_LIBCXXABI_BUILDING_LIBRARY -D_LIBCXXABI_NO_EXCEPTIONS -Ithird_party/libcxxabi/include -nostdinc++ -Ithird_party/libcxx/include $(W_NO_UNUSED_BUT_SET_VARIABLE) $(W_NO_MAYBE_UNINITIALIZED) -fvisibility=hidden
+$(LIBCXXABI_OBJS): CXXFLAGS += $(W_NO_CXX14_COMPAT)
+
+$(LIBDIR)/$(CONFIG)/libcxxabi.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP)  $(LIBCXXABI_OBJS) 
+	$(E) "[AR]      Creating $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libcxxabi.a
+	$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libcxxabi.a $(LIBCXXABI_OBJS) 
+ifeq ($(SYSTEM),Darwin)
+	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libcxxabi.a
+endif
+
+
+
+
+ifneq ($(NO_DEPS),true)
+-include $(LIBCXXABI_OBJS:.o=.dep)
+endif
+
+
 LIBGPR_SRC = \
 LIBGPR_SRC = \
     src/core/lib/gpr/alloc.cc \
     src/core/lib/gpr/alloc.cc \
     src/core/lib/gpr/arena.cc \
     src/core/lib/gpr/arena.cc \
@@ -3640,6 +3711,7 @@ PUBLIC_HEADERS_C += \
     include/grpc/grpc.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
     include/grpc/status.h \
@@ -4909,6 +4981,7 @@ PUBLIC_HEADERS_C += \
     include/grpc/grpc.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
     include/grpc/status.h \
@@ -5204,6 +5277,7 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/grpc.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
     include/grpc/status.h \
@@ -5774,6 +5848,7 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/grpc.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
     include/grpc/status.h \
@@ -6633,6 +6708,7 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/grpc.h \
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
     include/grpc/status.h \
@@ -10998,6 +11074,38 @@ endif
 endif
 endif
 
 
 
 
+EV_EPOLLEX_LINUX_TEST_SRC = \
+    test/core/iomgr/ev_epollex_linux_test.cc \
+
+EV_EPOLLEX_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLLEX_LINUX_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/ev_epollex_linux_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/ev_epollex_linux_test: $(EV_EPOLLEX_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(EV_EPOLLEX_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ev_epollex_linux_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/iomgr/ev_epollex_linux_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_ev_epollex_linux_test: $(EV_EPOLLEX_LINUX_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(EV_EPOLLEX_LINUX_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 EV_EPOLLSIG_LINUX_TEST_SRC = \
 EV_EPOLLSIG_LINUX_TEST_SRC = \
     test/core/iomgr/ev_epollsig_linux_test.cc \
     test/core/iomgr/ev_epollsig_linux_test.cc \
 
 

+ 52 - 0
build.yaml

@@ -173,6 +173,7 @@ filegroups:
   - include/grpc/support/thd_id.h
   - include/grpc/support/thd_id.h
   - include/grpc/support/time.h
   - include/grpc/support/time.h
   headers:
   headers:
+  - src/core/lib/gpr/alloc.h
   - src/core/lib/gpr/arena.h
   - src/core/lib/gpr/arena.h
   - src/core/lib/gpr/env.h
   - src/core/lib/gpr/env.h
   - src/core/lib/gpr/host_port.h
   - src/core/lib/gpr/host_port.h
@@ -393,6 +394,7 @@ filegroups:
   - include/grpc/grpc.h
   - include/grpc/grpc.h
   - include/grpc/grpc_posix.h
   - include/grpc/grpc_posix.h
   - include/grpc/grpc_security_constants.h
   - include/grpc/grpc_security_constants.h
+  - include/grpc/load_reporting.h
   - include/grpc/slice.h
   - include/grpc/slice.h
   - include/grpc/slice_buffer.h
   - include/grpc/slice_buffer.h
   - include/grpc/status.h
   - include/grpc/status.h
@@ -645,6 +647,8 @@ filegroups:
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
   src:
   src:
   - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
   - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
@@ -668,6 +672,8 @@ filegroups:
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
   src:
   src:
   - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
   - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
@@ -1367,6 +1373,32 @@ libs:
   deps:
   deps:
   - grpc
   - grpc
   secure: true
   secure: true
+- name: cxxabi
+  build: private
+  language: c
+  src:
+  - third_party/libcxxabi/src/abort_message.cpp
+  - third_party/libcxxabi/src/cxa_aux_runtime.cpp
+  - third_party/libcxxabi/src/cxa_default_handlers.cpp
+  - third_party/libcxxabi/src/cxa_demangle.cpp
+  - third_party/libcxxabi/src/cxa_exception_storage.cpp
+  - third_party/libcxxabi/src/cxa_guard.cpp
+  - third_party/libcxxabi/src/cxa_handlers.cpp
+  - third_party/libcxxabi/src/cxa_noexception.cpp
+  - third_party/libcxxabi/src/cxa_thread_atexit.cpp
+  - third_party/libcxxabi/src/cxa_unexpected.cpp
+  - third_party/libcxxabi/src/cxa_vector.cpp
+  - third_party/libcxxabi/src/cxa_virtual.cpp
+  - third_party/libcxxabi/src/fallback_malloc.cpp
+  - third_party/libcxxabi/src/private_typeinfo.cpp
+  - third_party/libcxxabi/src/stdlib_exception.cpp
+  - third_party/libcxxabi/src/stdlib_new_delete.cpp
+  - third_party/libcxxabi/src/stdlib_stdexcept.cpp
+  - third_party/libcxxabi/src/stdlib_typeinfo.cpp
+  build_system:
+  - Makefile
+  defaults: cxxabi
+  secure: false
 - name: gpr
 - name: gpr
   build: all
   build: all
   language: c
   language: c
@@ -2260,6 +2292,21 @@ targets:
   - gpr_test_util
   - gpr_test_util
   - gpr
   - gpr
   uses_polling: false
   uses_polling: false
+- name: ev_epollex_linux_test
+  cpu_cost: 3
+  build: test
+  language: c
+  src:
+  - test/core/iomgr/ev_epollex_linux_test.cc
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  exclude_iomgrs:
+  - uv
+  platforms:
+  - linux
 - name: ev_epollsig_linux_test
 - name: ev_epollsig_linux_test
   cpu_cost: 3
   cpu_cost: 3
   build: test
   build: test
@@ -5645,6 +5692,11 @@ defaults:
     CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
     CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
       -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
       -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
     CXXFLAGS: -fno-rtti -fno-exceptions
     CXXFLAGS: -fno-rtti -fno-exceptions
+  cxxabi:
+    CPPFLAGS: -D_LIBCPP_DISABLE_EXTERN_TEMPLATE -D_LIBCXXABI_BUILDING_LIBRARY -D_LIBCXXABI_NO_EXCEPTIONS
+      -Ithird_party/libcxxabi/include -nostdinc++ -Ithird_party/libcxx/include $(W_NO_UNUSED_BUT_SET_VARIABLE)
+      $(W_NO_MAYBE_UNINITIALIZED) -fvisibility=hidden
+    CXXFLAGS: $(W_NO_CXX14_COMPAT)
   global:
   global:
     COREFLAGS: -fno-rtti -fno-exceptions
     COREFLAGS: -fno-rtti -fno-exceptions
     CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
     CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1

+ 16 - 1
gRPC-C++.podspec

@@ -24,7 +24,7 @@ Pod::Spec.new do |s|
   s.name     = 'gRPC-C++'
   s.name     = 'gRPC-C++'
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
   # version = '1.14.0-dev'
   # version = '1.14.0-dev'
-  version = '0.0.2'
+  version = '0.0.3'
   s.version  = version
   s.version  = version
   s.summary  = 'gRPC C++ library'
   s.summary  = 'gRPC C++ library'
   s.homepage = 'https://grpc.io'
   s.homepage = 'https://grpc.io'
@@ -212,6 +212,7 @@ Pod::Spec.new do |s|
                       'src/cpp/util/string_ref.cc',
                       'src/cpp/util/string_ref.cc',
                       'src/cpp/util/time_cc.cc',
                       'src/cpp/util/time_cc.cc',
                       'src/cpp/codegen/codegen_init.cc',
                       'src/cpp/codegen/codegen_init.cc',
+                      'src/core/lib/gpr/alloc.h',
                       'src/core/lib/gpr/arena.h',
                       'src/core/lib/gpr/arena.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/host_port.h',
                       'src/core/lib/gpr/host_port.h',
@@ -479,6 +480,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
+                      'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h',
+                      'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                       'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
                       'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
                       'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
                       'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
@@ -501,6 +504,7 @@ Pod::Spec.new do |s|
                               'src/cpp/server/health/health.pb.h',
                               'src/cpp/server/health/health.pb.h',
                               'src/cpp/server/thread_pool_interface.h',
                               'src/cpp/server/thread_pool_interface.h',
                               'src/cpp/thread_manager/thread_manager.h',
                               'src/cpp/thread_manager/thread_manager.h',
+                              'src/core/lib/gpr/alloc.h',
                               'src/core/lib/gpr/arena.h',
                               'src/core/lib/gpr/arena.h',
                               'src/core/lib/gpr/env.h',
                               'src/core/lib/gpr/env.h',
                               'src/core/lib/gpr/host_port.h',
                               'src/core/lib/gpr/host_port.h',
@@ -662,6 +666,17 @@ Pod::Spec.new do |s|
                               'src/core/ext/transport/inproc/inproc_transport.h'
                               'src/core/ext/transport/inproc/inproc_transport.h'
   end
   end
 
 
+  s.subspec 'Protobuf' do |ss|
+    ss.header_mappings_dir = 'include/grpcpp'
+    ss.dependency "#{s.name}/Interface", version
+
+    ss.source_files = 'include/grpcpp/impl/codegen/proto_buffer_reader.h',
+                      'include/grpcpp/impl/codegen/proto_buffer_writer.h',
+                      'include/grpcpp/impl/codegen/proto_utils.h',
+                      'include/grpcpp/impl/codegen/config_protobuf.h',
+                      'include/grpcpp/impl/codegen/config_protobuf.h'
+  end
+
   s.prepare_command = <<-END_OF_COMMAND
   s.prepare_command = <<-END_OF_COMMAND
     find src/cpp/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
     find src/cpp/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
     find src/cpp/ -type f -path '*.grpc_back' -print0 | xargs -0 rm
     find src/cpp/ -type f -path '*.grpc_back' -print0 | xargs -0 rm

+ 9 - 2
gRPC-Core.podspec

@@ -168,6 +168,7 @@ Pod::Spec.new do |s|
                       'include/grpc/grpc.h',
                       'include/grpc/grpc.h',
                       'include/grpc/grpc_posix.h',
                       'include/grpc/grpc_posix.h',
                       'include/grpc/grpc_security_constants.h',
                       'include/grpc/grpc_security_constants.h',
+                      'include/grpc/load_reporting.h',
                       'include/grpc/slice.h',
                       'include/grpc/slice.h',
                       'include/grpc/slice_buffer.h',
                       'include/grpc/slice_buffer.h',
                       'include/grpc/status.h',
                       'include/grpc/status.h',
@@ -182,7 +183,8 @@ Pod::Spec.new do |s|
     ss.dependency 'nanopb', '~> 0.3'
     ss.dependency 'nanopb', '~> 0.3'
 
 
     # To save you from scrolling, this is the last part of the podspec.
     # To save you from scrolling, this is the last part of the podspec.
-    ss.source_files = 'src/core/lib/gpr/arena.h',
+    ss.source_files = 'src/core/lib/gpr/alloc.h',
+                      'src/core/lib/gpr/arena.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/host_port.h',
                       'src/core/lib/gpr/host_port.h',
                       'src/core/lib/gpr/mpscq.h',
                       'src/core/lib/gpr/mpscq.h',
@@ -488,6 +490,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
+                      'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h',
+                      'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                       'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
                       'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
                       'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
                       'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
@@ -800,7 +804,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/workarounds/workaround_utils.cc',
                       'src/core/ext/filters/workarounds/workaround_utils.cc',
                       'src/core/plugin_registry/grpc_plugin_registry.cc'
                       'src/core/plugin_registry/grpc_plugin_registry.cc'
 
 
-    ss.private_header_files = 'src/core/lib/gpr/arena.h',
+    ss.private_header_files = 'src/core/lib/gpr/alloc.h',
+                              'src/core/lib/gpr/arena.h',
                               'src/core/lib/gpr/env.h',
                               'src/core/lib/gpr/env.h',
                               'src/core/lib/gpr/host_port.h',
                               'src/core/lib/gpr/host_port.h',
                               'src/core/lib/gpr/mpscq.h',
                               'src/core/lib/gpr/mpscq.h',
@@ -1067,6 +1072,8 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
+                              'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h',
+                              'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                               'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                               'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
                               'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
                               'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
                               'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',

+ 4 - 0
grpc.gemspec

@@ -81,6 +81,7 @@ Gem::Specification.new do |s|
   s.files += %w( include/grpc/impl/codegen/sync_generic.h )
   s.files += %w( include/grpc/impl/codegen/sync_generic.h )
   s.files += %w( include/grpc/impl/codegen/sync_posix.h )
   s.files += %w( include/grpc/impl/codegen/sync_posix.h )
   s.files += %w( include/grpc/impl/codegen/sync_windows.h )
   s.files += %w( include/grpc/impl/codegen/sync_windows.h )
+  s.files += %w( src/core/lib/gpr/alloc.h )
   s.files += %w( src/core/lib/gpr/arena.h )
   s.files += %w( src/core/lib/gpr/arena.h )
   s.files += %w( src/core/lib/gpr/env.h )
   s.files += %w( src/core/lib/gpr/env.h )
   s.files += %w( src/core/lib/gpr/host_port.h )
   s.files += %w( src/core/lib/gpr/host_port.h )
@@ -173,6 +174,7 @@ Gem::Specification.new do |s|
   s.files += %w( include/grpc/grpc.h )
   s.files += %w( include/grpc/grpc.h )
   s.files += %w( include/grpc/grpc_posix.h )
   s.files += %w( include/grpc/grpc_posix.h )
   s.files += %w( include/grpc/grpc_security_constants.h )
   s.files += %w( include/grpc/grpc_security_constants.h )
+  s.files += %w( include/grpc/load_reporting.h )
   s.files += %w( include/grpc/slice.h )
   s.files += %w( include/grpc/slice.h )
   s.files += %w( include/grpc/slice_buffer.h )
   s.files += %w( include/grpc/slice_buffer.h )
   s.files += %w( include/grpc/status.h )
   s.files += %w( include/grpc/status.h )
@@ -425,6 +427,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.h )

+ 26 - 0
grpc.gyp

@@ -185,6 +185,32 @@
         'test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.cc',
         'test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.cc',
       ],
       ],
     },
     },
+    {
+      'target_name': 'cxxabi',
+      'type': 'static_library',
+      'dependencies': [
+      ],
+      'sources': [
+        'third_party/libcxxabi/src/abort_message.cpp',
+        'third_party/libcxxabi/src/cxa_aux_runtime.cpp',
+        'third_party/libcxxabi/src/cxa_default_handlers.cpp',
+        'third_party/libcxxabi/src/cxa_demangle.cpp',
+        'third_party/libcxxabi/src/cxa_exception_storage.cpp',
+        'third_party/libcxxabi/src/cxa_guard.cpp',
+        'third_party/libcxxabi/src/cxa_handlers.cpp',
+        'third_party/libcxxabi/src/cxa_noexception.cpp',
+        'third_party/libcxxabi/src/cxa_thread_atexit.cpp',
+        'third_party/libcxxabi/src/cxa_unexpected.cpp',
+        'third_party/libcxxabi/src/cxa_vector.cpp',
+        'third_party/libcxxabi/src/cxa_virtual.cpp',
+        'third_party/libcxxabi/src/fallback_malloc.cpp',
+        'third_party/libcxxabi/src/private_typeinfo.cpp',
+        'third_party/libcxxabi/src/stdlib_exception.cpp',
+        'third_party/libcxxabi/src/stdlib_new_delete.cpp',
+        'third_party/libcxxabi/src/stdlib_stdexcept.cpp',
+        'third_party/libcxxabi/src/stdlib_typeinfo.cpp',
+      ],
+    },
     {
     {
       'target_name': 'gpr',
       'target_name': 'gpr',
       'type': 'static_library',
       'type': 'static_library',

+ 1 - 0
include/grpc/module.modulemap

@@ -43,6 +43,7 @@ framework module grpc {
   header "grpc.h"
   header "grpc.h"
   header "grpc_posix.h"
   header "grpc_posix.h"
   header "grpc_security_constants.h"
   header "grpc_security_constants.h"
+  header "load_reporting.h"
   header "slice.h"
   header "slice.h"
   header "slice_buffer.h"
   header "slice_buffer.h"
   header "status.h"
   header "status.h"

+ 4 - 0
package.xml

@@ -86,6 +86,7 @@
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/gpr/alloc.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/arena.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/arena.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/env.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/env.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/host_port.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/gpr/host_port.h" role="src" />
@@ -178,6 +179,7 @@
     <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/load_reporting.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/status.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/status.h" role="src" />
@@ -430,6 +432,8 @@
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" role="src" />

+ 8 - 2
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc

@@ -74,6 +74,8 @@ struct grpc_ares_ev_driver {
   bool working;
   bool working;
   /** is this event driver being shut down */
   /** is this event driver being shut down */
   bool shutting_down;
   bool shutting_down;
+  /** request object that's using this ev driver */
+  grpc_ares_request* request;
 };
 };
 
 
 static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
 static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
@@ -92,6 +94,7 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
     GPR_ASSERT(ev_driver->fds == nullptr);
     GPR_ASSERT(ev_driver->fds == nullptr);
     GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
     GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
     ares_destroy(ev_driver->channel);
     ares_destroy(ev_driver->channel);
+    grpc_ares_complete_request_locked(ev_driver->request);
     gpr_free(ev_driver);
     gpr_free(ev_driver);
   }
   }
 }
 }
@@ -115,7 +118,8 @@ static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) {
 
 
 grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
 grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
                                               grpc_pollset_set* pollset_set,
                                               grpc_pollset_set* pollset_set,
-                                              grpc_combiner* combiner) {
+                                              grpc_combiner* combiner,
+                                              grpc_ares_request* request) {
   *ev_driver = static_cast<grpc_ares_ev_driver*>(
   *ev_driver = static_cast<grpc_ares_ev_driver*>(
       gpr_malloc(sizeof(grpc_ares_ev_driver)));
       gpr_malloc(sizeof(grpc_ares_ev_driver)));
   ares_options opts;
   ares_options opts;
@@ -139,10 +143,12 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
   (*ev_driver)->fds = nullptr;
   (*ev_driver)->fds = nullptr;
   (*ev_driver)->working = false;
   (*ev_driver)->working = false;
   (*ev_driver)->shutting_down = false;
   (*ev_driver)->shutting_down = false;
+  (*ev_driver)->request = request;
   return GRPC_ERROR_NONE;
   return GRPC_ERROR_NONE;
 }
 }
 
 
-void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver) {
+void grpc_ares_ev_driver_on_queries_complete_locked(
+    grpc_ares_ev_driver* ev_driver) {
   // We mark the event driver as being shut down. If the event driver
   // We mark the event driver as being shut down. If the event driver
   // is working, grpc_ares_notify_on_event_locked will shut down the
   // is working, grpc_ares_notify_on_event_locked will shut down the
   // fds; if it's not working, there are no fds to shut down.
   // fds; if it's not working, there are no fds to shut down.

+ 6 - 5
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h

@@ -22,6 +22,7 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/port_platform.h>
 
 
 #include <ares.h>
 #include <ares.h>
+#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
 #include "src/core/lib/gprpp/abstract.h"
 #include "src/core/lib/gprpp/abstract.h"
 #include "src/core/lib/iomgr/pollset_set.h"
 #include "src/core/lib/iomgr/pollset_set.h"
 
 
@@ -42,12 +43,12 @@ ares_channel* grpc_ares_ev_driver_get_channel_locked(
    created successfully. */
    created successfully. */
 grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
 grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
                                               grpc_pollset_set* pollset_set,
                                               grpc_pollset_set* pollset_set,
-                                              grpc_combiner* combiner);
+                                              grpc_combiner* combiner,
+                                              grpc_ares_request* request);
 
 
-/* Destroys \a ev_driver asynchronously. Pending lookups made on \a ev_driver
-   will be cancelled and their on_done callbacks will be invoked with a status
-   of ARES_ECANCELLED. */
-void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver);
+/* Called back when all DNS lookups have completed. */
+void grpc_ares_ev_driver_on_queries_complete_locked(
+    grpc_ares_ev_driver* ev_driver);
 
 
 /* Shutdown all the grpc_fds used by \a ev_driver */
 /* Shutdown all the grpc_fds used by \a ev_driver */
 void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver);
 void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver);

+ 4 - 1
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc

@@ -44,11 +44,13 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
       : as_(as) {
       : as_(as) {
     gpr_asprintf(&name_, "c-ares fd: %d", (int)as);
     gpr_asprintf(&name_, "c-ares fd: %d", (int)as);
     fd_ = grpc_fd_create((int)as, name_, false);
     fd_ = grpc_fd_create((int)as, name_, false);
-    grpc_pollset_set_add_fd(driver_pollset_set, fd_);
+    driver_pollset_set_ = driver_pollset_set;
+    grpc_pollset_set_add_fd(driver_pollset_set_, fd_);
   }
   }
 
 
   ~GrpcPolledFdPosix() {
   ~GrpcPolledFdPosix() {
     gpr_free(name_);
     gpr_free(name_);
+    grpc_pollset_set_del_fd(driver_pollset_set_, fd_);
     /* c-ares library will close the fd inside grpc_fd. This fd may be picked up
     /* c-ares library will close the fd inside grpc_fd. This fd may be picked up
        immediately by another thread, and should not be closed by the following
        immediately by another thread, and should not be closed by the following
        grpc_fd_orphan. */
        grpc_fd_orphan. */
@@ -81,6 +83,7 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
   char* name_;
   char* name_;
   ares_socket_t as_;
   ares_socket_t as_;
   grpc_fd* fd_;
   grpc_fd* fd_;
+  grpc_pollset_set* driver_pollset_set_;
 };
 };
 
 
 GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
 GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,

+ 22 - 21
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc

@@ -63,7 +63,7 @@ struct grpc_ares_request {
   /** the evernt driver used by this request */
   /** the evernt driver used by this request */
   grpc_ares_ev_driver* ev_driver;
   grpc_ares_ev_driver* ev_driver;
   /** number of ongoing queries */
   /** number of ongoing queries */
-  gpr_refcount pending_queries;
+  size_t pending_queries;
 
 
   /** is there at least one successful query, set in on_done_cb */
   /** is there at least one successful query, set in on_done_cb */
   bool success;
   bool success;
@@ -145,21 +145,25 @@ void grpc_cares_wrapper_test_only_address_sorting_sort(
 }
 }
 
 
 static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
 static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
-  gpr_ref(&r->pending_queries);
+  r->pending_queries++;
 }
 }
 
 
 static void grpc_ares_request_unref_locked(grpc_ares_request* r) {
 static void grpc_ares_request_unref_locked(grpc_ares_request* r) {
-  /* If there are no pending queries, invoke on_done callback and destroy the
+  r->pending_queries--;
+  if (r->pending_queries == 0u) {
+    grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver);
+  }
+}
+
+void grpc_ares_complete_request_locked(grpc_ares_request* r) {
+  /* Invoke on_done callback and destroy the
      request */
      request */
-  if (gpr_unref(&r->pending_queries)) {
-    grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out);
-    if (lb_addrs != nullptr) {
-      grpc_cares_wrapper_address_sorting_sort(lb_addrs);
-    }
-    GRPC_CLOSURE_SCHED(r->on_done, r->error);
-    grpc_ares_ev_driver_destroy_locked(r->ev_driver);
-    gpr_free(r);
+  grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out);
+  if (lb_addrs != nullptr) {
+    grpc_cares_wrapper_address_sorting_sort(lb_addrs);
   }
   }
+  GRPC_CLOSURE_SCHED(r->on_done, r->error);
+  gpr_free(r);
 }
 }
 
 
 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
@@ -399,20 +403,18 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
     }
     }
     port = gpr_strdup(default_port);
     port = gpr_strdup(default_port);
   }
   }
-  grpc_ares_ev_driver* ev_driver;
-  error = grpc_ares_ev_driver_create_locked(&ev_driver, interested_parties,
-                                            combiner);
-  if (error != GRPC_ERROR_NONE) goto error_cleanup;
-
   r = static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
   r = static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
-  r->ev_driver = ev_driver;
+  r->ev_driver = nullptr;
   r->on_done = on_done;
   r->on_done = on_done;
   r->lb_addrs_out = addrs;
   r->lb_addrs_out = addrs;
   r->service_config_json_out = service_config_json;
   r->service_config_json_out = service_config_json;
   r->success = false;
   r->success = false;
   r->error = GRPC_ERROR_NONE;
   r->error = GRPC_ERROR_NONE;
+  r->pending_queries = 0;
+  error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
+                                            combiner, r);
+  if (error != GRPC_ERROR_NONE) goto error_cleanup;
   channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
   channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
-
   // If dns_server is specified, use it.
   // If dns_server is specified, use it.
   if (dns_server != nullptr) {
   if (dns_server != nullptr) {
     gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
     gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
@@ -437,7 +439,6 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
       error = grpc_error_set_str(
       error = grpc_error_set_str(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
-      gpr_free(r);
       goto error_cleanup;
       goto error_cleanup;
     }
     }
     int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
     int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
@@ -447,11 +448,10 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
                    ares_strerror(status));
                    ares_strerror(status));
       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
       gpr_free(error_msg);
       gpr_free(error_msg);
-      gpr_free(r);
       goto error_cleanup;
       goto error_cleanup;
     }
     }
   }
   }
-  gpr_ref_init(&r->pending_queries, 1);
+  r->pending_queries = 1;
   if (grpc_ipv6_loopback_available()) {
   if (grpc_ipv6_loopback_available()) {
     hr = create_hostbyname_request_locked(r, host, strhtons(port),
     hr = create_hostbyname_request_locked(r, host, strhtons(port),
                                           false /* is_balancer */);
                                           false /* is_balancer */);
@@ -487,6 +487,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
 
 
 error_cleanup:
 error_cleanup:
   GRPC_CLOSURE_SCHED(on_done, error);
   GRPC_CLOSURE_SCHED(on_done, error);
+  gpr_free(r);
   gpr_free(host);
   gpr_free(host);
   gpr_free(port);
   gpr_free(port);
   return nullptr;
   return nullptr;

+ 4 - 0
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h

@@ -66,6 +66,10 @@ grpc_error* grpc_ares_init(void);
    it has been called the same number of times as grpc_ares_init(). */
    it has been called the same number of times as grpc_ares_init(). */
 void grpc_ares_cleanup(void);
 void grpc_ares_cleanup(void);
 
 
+/** Schedules the desired callback for request completion
+ * and destroys the grpc_ares_request */
+void grpc_ares_complete_request_locked(grpc_ares_request* request);
+
 /* Exposed only for testing */
 /* Exposed only for testing */
 void grpc_cares_wrapper_test_only_address_sorting_sort(
 void grpc_cares_wrapper_test_only_address_sorting_sort(
     grpc_lb_addresses* lb_addrs);
     grpc_lb_addresses* lb_addrs);

+ 19 - 6
src/core/ext/filters/client_channel/subchannel.cc

@@ -38,6 +38,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/stats.h"
+#include "src/core/lib/gpr/alloc.h"
 #include "src/core/lib/gprpp/debug_location.h"
 #include "src/core/lib/gprpp/debug_location.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
@@ -140,9 +141,13 @@ struct grpc_subchannel_call {
   grpc_closure* schedule_closure_after_destroy;
   grpc_closure* schedule_closure_after_destroy;
 };
 };
 
 
-#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack*)((call) + 1))
-#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
-  (((grpc_subchannel_call*)(callstack)) - 1)
+#define SUBCHANNEL_CALL_TO_CALL_STACK(call)                          \
+  (grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
+                                         sizeof(grpc_subchannel_call)))
+#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack)           \
+  (grpc_subchannel_call*)(((char*)(call_stack)) -         \
+                          GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
+                              sizeof(grpc_subchannel_call)))
 
 
 static void on_subchannel_connected(void* subchannel, grpc_error* error);
 static void on_subchannel_connected(void* subchannel, grpc_error* error);
 
 
@@ -783,9 +788,17 @@ void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
 
 
 grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
 grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
                                             grpc_subchannel_call** call) {
                                             grpc_subchannel_call** call) {
-  *call = static_cast<grpc_subchannel_call*>(gpr_arena_alloc(
-      args.arena, sizeof(grpc_subchannel_call) +
-                      channel_stack_->call_stack_size + args.parent_data_size));
+  size_t allocation_size =
+      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call));
+  if (args.parent_data_size > 0) {
+    allocation_size +=
+        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) +
+        args.parent_data_size;
+  } else {
+    allocation_size += channel_stack_->call_stack_size;
+  }
+  *call = static_cast<grpc_subchannel_call*>(
+      gpr_arena_alloc(args.arena, allocation_size));
   grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
   grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
   RefCountedPtr<ConnectedSubchannel> connection =
   RefCountedPtr<ConnectedSubchannel> connection =
       Ref(DEBUG_LOCATION, "subchannel_call");
       Ref(DEBUG_LOCATION, "subchannel_call");

+ 22 - 24
src/core/lib/channel/channel_stack.cc

@@ -21,6 +21,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/gpr/alloc.h"
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
@@ -43,16 +44,12 @@ grpc_core::TraceFlag grpc_trace_channel(false, "channel");
      per-filter memory, aligned to GPR_MAX_ALIGNMENT
      per-filter memory, aligned to GPR_MAX_ALIGNMENT
    } */
    } */
 
 
-/* Given a size, round up to the next multiple of sizeof(void*) */
-#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
-  (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
-
 size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
 size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
                                size_t filter_count) {
                                size_t filter_count) {
   /* always need the header, and size for the channel elements */
   /* always need the header, and size for the channel elements */
-  size_t size =
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
-      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
+  size_t size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
+                GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
+                                               sizeof(grpc_channel_element));
   size_t i;
   size_t i;
 
 
   GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
   GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
@@ -60,19 +57,19 @@ size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
 
 
   /* add the size for each filter */
   /* add the size for each filter */
   for (i = 0; i < filter_count; i++) {
   for (i = 0; i < filter_count; i++) {
-    size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
+    size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
   }
   }
 
 
   return size;
   return size;
 }
 }
 
 
-#define CHANNEL_ELEMS_FROM_STACK(stk)                                 \
-  ((grpc_channel_element*)((char*)(stk) + ROUND_UP_TO_ALIGNMENT_SIZE( \
+#define CHANNEL_ELEMS_FROM_STACK(stk)                                     \
+  ((grpc_channel_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
                                               sizeof(grpc_channel_stack))))
                                               sizeof(grpc_channel_stack))))
 
 
-#define CALL_ELEMS_FROM_STACK(stk)     \
-  ((grpc_call_element*)((char*)(stk) + \
-                        ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack))))
+#define CALL_ELEMS_FROM_STACK(stk)                                     \
+  ((grpc_call_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
+                                           sizeof(grpc_call_stack))))
 
 
 grpc_channel_element* grpc_channel_stack_element(
 grpc_channel_element* grpc_channel_stack_element(
     grpc_channel_stack* channel_stack, size_t index) {
     grpc_channel_stack* channel_stack, size_t index) {
@@ -95,8 +92,8 @@ grpc_error* grpc_channel_stack_init(
     const grpc_channel_args* channel_args, grpc_transport* optional_transport,
     const grpc_channel_args* channel_args, grpc_transport* optional_transport,
     const char* name, grpc_channel_stack* stack) {
     const char* name, grpc_channel_stack* stack) {
   size_t call_size =
   size_t call_size =
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
-      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
+      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
+      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
   grpc_channel_element* elems;
   grpc_channel_element* elems;
   grpc_channel_element_args args;
   grpc_channel_element_args args;
   char* user_data;
   char* user_data;
@@ -106,9 +103,9 @@ grpc_error* grpc_channel_stack_init(
   GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
   GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
                        name);
                        name);
   elems = CHANNEL_ELEMS_FROM_STACK(stack);
   elems = CHANNEL_ELEMS_FROM_STACK(stack);
-  user_data =
-      (reinterpret_cast<char*>(elems)) +
-      ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
+  user_data = (reinterpret_cast<char*>(elems)) +
+              GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
+                                             sizeof(grpc_channel_element));
 
 
   /* init per-filter data */
   /* init per-filter data */
   grpc_error* first_error = GRPC_ERROR_NONE;
   grpc_error* first_error = GRPC_ERROR_NONE;
@@ -128,8 +125,9 @@ grpc_error* grpc_channel_stack_init(
         GRPC_ERROR_UNREF(error);
         GRPC_ERROR_UNREF(error);
       }
       }
     }
     }
-    user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
-    call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
+    user_data +=
+        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
+    call_size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
   }
   }
 
 
   GPR_ASSERT(user_data > (char*)stack);
   GPR_ASSERT(user_data > (char*)stack);
@@ -166,7 +164,7 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
                        destroy_arg, "CALL_STACK");
                        destroy_arg, "CALL_STACK");
   call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack);
   call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack);
   user_data = (reinterpret_cast<char*>(call_elems)) +
   user_data = (reinterpret_cast<char*>(call_elems)) +
-              ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
+              GPR_ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
 
 
   /* init per-filter data */
   /* init per-filter data */
   grpc_error* first_error = GRPC_ERROR_NONE;
   grpc_error* first_error = GRPC_ERROR_NONE;
@@ -184,7 +182,7 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
       }
       }
     }
     }
     user_data +=
     user_data +=
-        ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
+        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
   }
   }
   return first_error;
   return first_error;
 }
 }
@@ -243,11 +241,11 @@ grpc_channel_stack* grpc_channel_stack_from_top_element(
     grpc_channel_element* elem) {
     grpc_channel_element* elem) {
   return reinterpret_cast<grpc_channel_stack*>(
   return reinterpret_cast<grpc_channel_stack*>(
       reinterpret_cast<char*>(elem) -
       reinterpret_cast<char*>(elem) -
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)));
+      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)));
 }
 }
 
 
 grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) {
 grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) {
   return reinterpret_cast<grpc_call_stack*>(
   return reinterpret_cast<grpc_call_stack*>(
       reinterpret_cast<char*>(elem) -
       reinterpret_cast<char*>(elem) -
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)));
+      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)));
 }
 }

+ 4 - 1
src/core/lib/channel/channelz.cc

@@ -113,7 +113,10 @@ grpc_connectivity_state ChannelNode::GetConnectivityState() {
   if (channel_ == nullptr) {
   if (channel_ == nullptr) {
     return GRPC_CHANNEL_SHUTDOWN;
     return GRPC_CHANNEL_SHUTDOWN;
   } else {
   } else {
-    return grpc_channel_check_connectivity_state(channel_, false);
+    // TODO(ncteisen): re-enable this once we have cleaned up all of the
+    // internal dependency issues.
+    // return grpc_channel_check_connectivity_state(channel_, false);
+    return GRPC_CHANNEL_IDLE;
   }
   }
 }
 }
 
 

+ 28 - 0
src/core/lib/gpr/alloc.h

@@ -0,0 +1,28 @@
+/*
+ *
+ * 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_GPR_ALLOC_H
+#define GRPC_CORE_LIB_GPR_ALLOC_H
+
+#include <grpc/support/port_platform.h>
+
+/// Given a size, round up to the next multiple of sizeof(void*).
+#define GPR_ROUND_UP_TO_ALIGNMENT_SIZE(x) \
+  (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
+
+#endif /* GRPC_CORE_LIB_GPR_ALLOC_H */

+ 8 - 8
src/core/lib/gpr/arena.cc

@@ -26,6 +26,8 @@
 #include <grpc/support/atm.h>
 #include <grpc/support/atm.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 
 
+#include "src/core/lib/gpr/alloc.h"
+
 // Uncomment this to use a simple arena that simply allocates the
 // Uncomment this to use a simple arena that simply allocates the
 // requested amount of memory for each call to gpr_arena_alloc().  This
 // requested amount of memory for each call to gpr_arena_alloc().  This
 // effectively eliminates the efficiency gain of using an arena, but it
 // effectively eliminates the efficiency gain of using an arena, but it
@@ -74,8 +76,6 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
 // arena API to C++, we should consider replacing gpr_arena_alloc() with a
 // arena API to C++, we should consider replacing gpr_arena_alloc() with a
 // template that takes the type of the value being allocated, which
 // template that takes the type of the value being allocated, which
 // would allow us to use the alignment actually needed by the caller.
 // would allow us to use the alignment actually needed by the caller.
-#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
-  (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
 
 
 typedef struct zone {
 typedef struct zone {
   size_t size_begin;
   size_t size_begin;
@@ -95,9 +95,9 @@ static void* zalloc_aligned(size_t size) {
 }
 }
 
 
 gpr_arena* gpr_arena_create(size_t initial_size) {
 gpr_arena* gpr_arena_create(size_t initial_size) {
-  initial_size = ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
+  initial_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
   gpr_arena* a = static_cast<gpr_arena*>(zalloc_aligned(
   gpr_arena* a = static_cast<gpr_arena*>(zalloc_aligned(
-      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size));
+      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size));
   a->initial_zone.size_end = initial_size;
   a->initial_zone.size_end = initial_size;
   return a;
   return a;
 }
 }
@@ -115,7 +115,7 @@ size_t gpr_arena_destroy(gpr_arena* arena) {
 }
 }
 
 
 void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
 void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
-  size = ROUND_UP_TO_ALIGNMENT_SIZE(size);
+  size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size);
   size_t start = static_cast<size_t>(
   size_t start = static_cast<size_t>(
       gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size));
       gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size));
   zone* z = &arena->initial_zone;
   zone* z = &arena->initial_zone;
@@ -125,7 +125,7 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
       size_t next_z_size =
       size_t next_z_size =
           static_cast<size_t>(gpr_atm_no_barrier_load(&arena->size_so_far));
           static_cast<size_t>(gpr_atm_no_barrier_load(&arena->size_so_far));
       next_z = static_cast<zone*>(zalloc_aligned(
       next_z = static_cast<zone*>(zalloc_aligned(
-          ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + next_z_size));
+          GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + next_z_size));
       next_z->size_begin = z->size_end;
       next_z->size_begin = z->size_end;
       next_z->size_end = z->size_end + next_z_size;
       next_z->size_end = z->size_end + next_z_size;
       if (!gpr_atm_rel_cas(&z->next_atm, static_cast<gpr_atm>(NULL),
       if (!gpr_atm_rel_cas(&z->next_atm, static_cast<gpr_atm>(NULL),
@@ -143,9 +143,9 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
   GPR_ASSERT(start + size <= z->size_end);
   GPR_ASSERT(start + size <= z->size_end);
   char* ptr = (z == &arena->initial_zone)
   char* ptr = (z == &arena->initial_zone)
                   ? reinterpret_cast<char*>(arena) +
                   ? reinterpret_cast<char*>(arena) +
-                        ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena))
+                        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena))
                   : reinterpret_cast<char*>(z) +
                   : reinterpret_cast<char*>(z) +
-                        ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
+                        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
   return ptr + start - z->size_begin;
   return ptr + start - z->size_begin;
 }
 }
 
 

+ 1 - 1
src/core/lib/gprpp/thd_posix.cc

@@ -105,7 +105,7 @@ class ThreadInternalsPosix
 
 
     GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
     GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
 
 
-    if (!success) {
+    if (!(*success)) {
       /* don't use gpr_free, as this was allocated using malloc (see above) */
       /* don't use gpr_free, as this was allocated using malloc (see above) */
       free(info);
       free(info);
       grpc_core::Fork::DecThreadCount();
       grpc_core::Fork::DecThreadCount();

+ 73 - 24
src/core/lib/iomgr/ev_epollex_linux.cc

@@ -104,8 +104,10 @@ struct pollable {
   int epfd;
   int epfd;
   grpc_wakeup_fd wakeup;
   grpc_wakeup_fd wakeup;
 
 
-  // only for type fd... one ref to the owner fd
-  grpc_fd* owner_fd;
+  // The following are relevant only for type PO_FD
+  grpc_fd* owner_fd;       // Set to the owner_fd if the type is PO_FD
+  gpr_mu owner_orphan_mu;  // Synchronizes access to owner_orphaned field
+  bool owner_orphaned;     // Is the owner fd orphaned
 
 
   grpc_pollset_set* pollset_set;
   grpc_pollset_set* pollset_set;
   pollable* next;
   pollable* next;
@@ -338,21 +340,45 @@ static void ref_by(grpc_fd* fd, int n) {
   GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
   GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
 }
 }
 
 
+#ifndef NDEBUG
+#define INVALIDATE_FD(fd) invalidate_fd(fd)
+/* Since an fd is never really destroyed (i.e gpr_free() is not called), it is
+ * hard to cases where fd fields are accessed even after calling fd_destroy().
+ * The following invalidates fd fields to make catching such errors easier */
+static void invalidate_fd(grpc_fd* fd) {
+  fd->fd = -1;
+  fd->salt = -1;
+  gpr_atm_no_barrier_store(&fd->refst, -1);
+  memset(&fd->orphan_mu, -1, sizeof(fd->orphan_mu));
+  memset(&fd->pollable_mu, -1, sizeof(fd->pollable_mu));
+  fd->pollable_obj = nullptr;
+  fd->on_done_closure = nullptr;
+  gpr_atm_no_barrier_store(&fd->read_notifier_pollset, 0);
+  memset(&fd->iomgr_object, -1, sizeof(fd->iomgr_object));
+  fd->track_err = false;
+}
+#else
+#define INVALIDATE_FD(fd)
+#endif
+
+/* Uninitialize and add to the freelist */
 static void fd_destroy(void* arg, grpc_error* error) {
 static void fd_destroy(void* arg, grpc_error* error) {
   grpc_fd* fd = static_cast<grpc_fd*>(arg);
   grpc_fd* fd = static_cast<grpc_fd*>(arg);
-  /* Add the fd to the freelist */
   grpc_iomgr_unregister_object(&fd->iomgr_object);
   grpc_iomgr_unregister_object(&fd->iomgr_object);
   POLLABLE_UNREF(fd->pollable_obj, "fd_pollable");
   POLLABLE_UNREF(fd->pollable_obj, "fd_pollable");
   gpr_mu_destroy(&fd->pollable_mu);
   gpr_mu_destroy(&fd->pollable_mu);
   gpr_mu_destroy(&fd->orphan_mu);
   gpr_mu_destroy(&fd->orphan_mu);
-  gpr_mu_lock(&fd_freelist_mu);
-  fd->freelist_next = fd_freelist;
-  fd_freelist = fd;
 
 
   fd->read_closure->DestroyEvent();
   fd->read_closure->DestroyEvent();
   fd->write_closure->DestroyEvent();
   fd->write_closure->DestroyEvent();
   fd->error_closure->DestroyEvent();
   fd->error_closure->DestroyEvent();
 
 
+  INVALIDATE_FD(fd);
+
+  /* Add the fd to the freelist */
+  gpr_mu_lock(&fd_freelist_mu);
+  fd->freelist_next = fd_freelist;
+  fd_freelist = fd;
   gpr_mu_unlock(&fd_freelist_mu);
   gpr_mu_unlock(&fd_freelist_mu);
 }
 }
 
 
@@ -408,20 +434,18 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
     new_fd->error_closure.Init();
     new_fd->error_closure.Init();
   }
   }
 
 
-  gpr_mu_init(&new_fd->pollable_mu);
-  gpr_mu_init(&new_fd->orphan_mu);
-  new_fd->pollable_obj = nullptr;
-  gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
   new_fd->fd = fd;
   new_fd->fd = fd;
-  new_fd->track_err = track_err;
   new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1);
   new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1);
+  gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
+  gpr_mu_init(&new_fd->orphan_mu);
+  gpr_mu_init(&new_fd->pollable_mu);
+  new_fd->pollable_obj = nullptr;
   new_fd->read_closure->InitEvent();
   new_fd->read_closure->InitEvent();
   new_fd->write_closure->InitEvent();
   new_fd->write_closure->InitEvent();
   new_fd->error_closure->InitEvent();
   new_fd->error_closure->InitEvent();
-  gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
-
   new_fd->freelist_next = nullptr;
   new_fd->freelist_next = nullptr;
   new_fd->on_done_closure = nullptr;
   new_fd->on_done_closure = nullptr;
+  gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
 
 
   char* fd_name;
   char* fd_name;
   gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
   gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
@@ -432,6 +456,8 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
   }
   }
 #endif
 #endif
   gpr_free(fd_name);
   gpr_free(fd_name);
+
+  new_fd->track_err = track_err;
   return new_fd;
   return new_fd;
 }
 }
 
 
@@ -446,6 +472,17 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
 
 
   gpr_mu_lock(&fd->orphan_mu);
   gpr_mu_lock(&fd->orphan_mu);
 
 
+  // Get the fd->pollable_obj and set the owner_orphaned on that pollable to
+  // true so that the pollable will no longer access its owner_fd field.
+  gpr_mu_lock(&fd->pollable_mu);
+  pollable* pollable_obj = fd->pollable_obj;
+  gpr_mu_unlock(&fd->pollable_mu);
+
+  if (pollable_obj) {
+    gpr_mu_lock(&pollable_obj->owner_orphan_mu);
+    pollable_obj->owner_orphaned = true;
+  }
+
   fd->on_done_closure = on_done;
   fd->on_done_closure = on_done;
 
 
   /* If release_fd is not NULL, we should be relinquishing control of the file
   /* If release_fd is not NULL, we should be relinquishing control of the file
@@ -467,6 +504,10 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
 
 
   GRPC_CLOSURE_SCHED(fd->on_done_closure, GRPC_ERROR_NONE);
   GRPC_CLOSURE_SCHED(fd->on_done_closure, GRPC_ERROR_NONE);
 
 
+  if (pollable_obj) {
+    gpr_mu_unlock(&pollable_obj->owner_orphan_mu);
+  }
+
   gpr_mu_unlock(&fd->orphan_mu);
   gpr_mu_unlock(&fd->orphan_mu);
 
 
   UNREF_BY(fd, 2, reason); /* Drop the reference */
   UNREF_BY(fd, 2, reason); /* Drop the reference */
@@ -551,6 +592,8 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) {
   gpr_mu_init(&(*p)->mu);
   gpr_mu_init(&(*p)->mu);
   (*p)->epfd = epfd;
   (*p)->epfd = epfd;
   (*p)->owner_fd = nullptr;
   (*p)->owner_fd = nullptr;
+  gpr_mu_init(&(*p)->owner_orphan_mu);
+  (*p)->owner_orphaned = false;
   (*p)->pollset_set = nullptr;
   (*p)->pollset_set = nullptr;
   (*p)->next = (*p)->prev = *p;
   (*p)->next = (*p)->prev = *p;
   (*p)->root_worker = nullptr;
   (*p)->root_worker = nullptr;
@@ -590,6 +633,7 @@ static void pollable_unref(pollable* p, int line, const char* reason) {
     GRPC_FD_TRACE("pollable_unref: Closing epfd: %d", p->epfd);
     GRPC_FD_TRACE("pollable_unref: Closing epfd: %d", p->epfd);
     close(p->epfd);
     close(p->epfd);
     grpc_wakeup_fd_destroy(&p->wakeup);
     grpc_wakeup_fd_destroy(&p->wakeup);
+    gpr_mu_destroy(&p->owner_orphan_mu);
     gpr_free(p);
     gpr_free(p);
   }
   }
 }
 }
@@ -846,10 +890,15 @@ static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); }
 
 
 static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); }
 static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); }
 
 
-static grpc_error* fd_get_or_become_pollable(grpc_fd* fd, pollable** p) {
+/* Get the pollable_obj attached to this fd. If none is attached, create a new
+ * pollable object (of type PO_FD), attach it to the fd and return it
+ *
+ * Note that if a pollable object is already attached to the fd, it may be of
+ * either PO_FD or PO_MULTI type */
+static grpc_error* get_fd_pollable(grpc_fd* fd, pollable** p) {
   gpr_mu_lock(&fd->pollable_mu);
   gpr_mu_lock(&fd->pollable_mu);
   grpc_error* error = GRPC_ERROR_NONE;
   grpc_error* error = GRPC_ERROR_NONE;
-  static const char* err_desc = "fd_get_or_become_pollable";
+  static const char* err_desc = "get_fd_pollable";
   if (fd->pollable_obj == nullptr) {
   if (fd->pollable_obj == nullptr) {
     if (append_error(&error, pollable_create(PO_FD, &fd->pollable_obj),
     if (append_error(&error, pollable_create(PO_FD, &fd->pollable_obj),
                      err_desc)) {
                      err_desc)) {
@@ -1186,7 +1235,7 @@ static grpc_error* pollset_transition_pollable_from_empty_to_fd_locked(
   }
   }
   append_error(&error, pollset_kick_all(pollset), err_desc);
   append_error(&error, pollset_kick_all(pollset), err_desc);
   POLLABLE_UNREF(pollset->active_pollable, "pollset");
   POLLABLE_UNREF(pollset->active_pollable, "pollset");
-  append_error(&error, fd_get_or_become_pollable(fd, &pollset->active_pollable),
+  append_error(&error, get_fd_pollable(fd, &pollset->active_pollable),
                err_desc);
                err_desc);
   return error;
   return error;
 }
 }
@@ -1230,9 +1279,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) {
       error = pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd);
       error = pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd);
       break;
       break;
     case PO_FD:
     case PO_FD:
-      gpr_mu_lock(&po_at_start->owner_fd->orphan_mu);
-      if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) &
-           1) == 0) {
+      gpr_mu_lock(&po_at_start->owner_orphan_mu);
+      if (po_at_start->owner_orphaned) {
         error =
         error =
             pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd);
             pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd);
       } else {
       } else {
@@ -1240,7 +1288,7 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) {
         error =
         error =
             pollset_transition_pollable_from_fd_to_multi_locked(pollset, fd);
             pollset_transition_pollable_from_fd_to_multi_locked(pollset, fd);
       }
       }
-      gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu);
+      gpr_mu_unlock(&po_at_start->owner_orphan_mu);
       break;
       break;
     case PO_MULTI:
     case PO_MULTI:
       error = pollable_add_fd(pollset->active_pollable, fd);
       error = pollable_add_fd(pollset->active_pollable, fd);
@@ -1276,16 +1324,17 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset,
       append_error(&error, pollset_kick_all(pollset), err_desc);
       append_error(&error, pollset_kick_all(pollset), err_desc);
       break;
       break;
     case PO_FD:
     case PO_FD:
-      gpr_mu_lock(&po_at_start->owner_fd->orphan_mu);
-      if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) &
-           1) == 0) {
+      gpr_mu_lock(&po_at_start->owner_orphan_mu);
+      if (po_at_start->owner_orphaned) {
+        // Unlock before Unref'ing the pollable
+        gpr_mu_unlock(&po_at_start->owner_orphan_mu);
         POLLABLE_UNREF(pollset->active_pollable, "pollset");
         POLLABLE_UNREF(pollset->active_pollable, "pollset");
         error = pollable_create(PO_MULTI, &pollset->active_pollable);
         error = pollable_create(PO_MULTI, &pollset->active_pollable);
       } else {
       } else {
         error = pollset_transition_pollable_from_fd_to_multi_locked(pollset,
         error = pollset_transition_pollable_from_fd_to_multi_locked(pollset,
                                                                     nullptr);
                                                                     nullptr);
+        gpr_mu_unlock(&po_at_start->owner_orphan_mu);
       }
       }
-      gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu);
       break;
       break;
     case PO_MULTI:
     case PO_MULTI:
       break;
       break;

+ 2 - 0
src/core/lib/iomgr/iomgr.cc

@@ -70,6 +70,8 @@ static size_t count_objects(void) {
   return n;
   return n;
 }
 }
 
 
+size_t grpc_iomgr_count_objects_for_testing(void) { return count_objects(); }
+
 static void dump_objects(const char* kind) {
 static void dump_objects(const char* kind) {
   grpc_iomgr_object* obj;
   grpc_iomgr_object* obj;
   for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
   for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {

+ 5 - 0
src/core/lib/iomgr/iomgr.h

@@ -23,6 +23,8 @@
 
 
 #include "src/core/lib/iomgr/port.h"
 #include "src/core/lib/iomgr/port.h"
 
 
+#include <stdlib.h>
+
 /** Initializes the iomgr. */
 /** Initializes the iomgr. */
 void grpc_iomgr_init();
 void grpc_iomgr_init();
 
 
@@ -33,4 +35,7 @@ void grpc_iomgr_start();
  * exec_ctx. */
  * exec_ctx. */
 void grpc_iomgr_shutdown();
 void grpc_iomgr_shutdown();
 
 
+/* Exposed only for testing */
+size_t grpc_iomgr_count_objects_for_testing();
+
 #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */
 #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */

+ 0 - 1
src/core/lib/iomgr/timer_manager.cc

@@ -277,7 +277,6 @@ static void start_threads(void) {
     g_threaded = true;
     g_threaded = true;
     start_timer_thread_and_unlock();
     start_timer_thread_and_unlock();
   } else {
   } else {
-    g_threaded = false;
     gpr_mu_unlock(&g_mu);
     gpr_mu_unlock(&g_mu);
   }
   }
 }
 }

+ 4 - 4
src/core/lib/security/context/security_context.cc

@@ -21,6 +21,7 @@
 #include <string.h>
 #include <string.h>
 
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/arena.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -99,10 +100,10 @@ void grpc_client_security_context_destroy(void* ctx) {
 }
 }
 
 
 /* --- grpc_server_security_context --- */
 /* --- grpc_server_security_context --- */
-
-grpc_server_security_context* grpc_server_security_context_create(void) {
+grpc_server_security_context* grpc_server_security_context_create(
+    gpr_arena* arena) {
   return static_cast<grpc_server_security_context*>(
   return static_cast<grpc_server_security_context*>(
-      gpr_zalloc(sizeof(grpc_server_security_context)));
+      gpr_arena_alloc(arena, sizeof(grpc_server_security_context)));
 }
 }
 
 
 void grpc_server_security_context_destroy(void* ctx) {
 void grpc_server_security_context_destroy(void* ctx) {
@@ -112,7 +113,6 @@ void grpc_server_security_context_destroy(void* ctx) {
   if (c->extension.instance != nullptr && c->extension.destroy != nullptr) {
   if (c->extension.instance != nullptr && c->extension.destroy != nullptr) {
     c->extension.destroy(c->extension.instance);
     c->extension.destroy(c->extension.instance);
   }
   }
-  gpr_free(ctx);
 }
 }
 
 
 /* --- grpc_auth_context --- */
 /* --- grpc_auth_context --- */

+ 4 - 1
src/core/lib/security/context/security_context.h

@@ -26,6 +26,8 @@
 
 
 extern grpc_core::DebugOnlyTraceFlag grpc_trace_auth_context_refcount;
 extern grpc_core::DebugOnlyTraceFlag grpc_trace_auth_context_refcount;
 
 
+struct gpr_arena;
+
 /* --- grpc_auth_context ---
 /* --- grpc_auth_context ---
 
 
    High level authentication context object. Can optionally be chained. */
    High level authentication context object. Can optionally be chained. */
@@ -101,7 +103,8 @@ typedef struct {
   grpc_security_context_extension extension;
   grpc_security_context_extension extension;
 } grpc_server_security_context;
 } grpc_server_security_context;
 
 
-grpc_server_security_context* grpc_server_security_context_create(void);
+grpc_server_security_context* grpc_server_security_context_create(
+    gpr_arena* arena);
 void grpc_server_security_context_destroy(void* ctx);
 void grpc_server_security_context_destroy(void* ctx);
 
 
 /* --- Channel args for auth context --- */
 /* --- Channel args for auth context --- */

+ 4 - 5
src/core/lib/security/transport/server_auth_filter.cc

@@ -44,7 +44,6 @@ struct call_data {
   grpc_metadata_array md;
   grpc_metadata_array md;
   const grpc_metadata* consumed_md;
   const grpc_metadata* consumed_md;
   size_t num_consumed_md;
   size_t num_consumed_md;
-  grpc_auth_context* auth_context;
   grpc_closure cancel_closure;
   grpc_closure cancel_closure;
   gpr_atm state;  // async_state
   gpr_atm state;  // async_state
 };
 };
@@ -178,7 +177,7 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
       calld->md = metadata_batch_to_md_array(
       calld->md = metadata_batch_to_md_array(
           batch->payload->recv_initial_metadata.recv_initial_metadata);
           batch->payload->recv_initial_metadata.recv_initial_metadata);
       chand->creds->processor.process(
       chand->creds->processor.process(
-          chand->creds->processor.state, calld->auth_context,
+          chand->creds->processor.state, chand->auth_context,
           calld->md.metadata, calld->md.count, on_md_processing_done, elem);
           calld->md.metadata, calld->md.count, on_md_processing_done, elem);
       return;
       return;
     }
     }
@@ -214,9 +213,9 @@ static grpc_error* init_call_elem(grpc_call_element* elem,
   // Create server security context.  Set its auth context from channel
   // Create server security context.  Set its auth context from channel
   // data and save it in the call context.
   // data and save it in the call context.
   grpc_server_security_context* server_ctx =
   grpc_server_security_context* server_ctx =
-      grpc_server_security_context_create();
-  server_ctx->auth_context = grpc_auth_context_create(chand->auth_context);
-  calld->auth_context = server_ctx->auth_context;
+      grpc_server_security_context_create(args->arena);
+  server_ctx->auth_context =
+      GRPC_AUTH_CONTEXT_REF(chand->auth_context, "server_auth_filter");
   if (args->context[GRPC_CONTEXT_SECURITY].value != nullptr) {
   if (args->context[GRPC_CONTEXT_SECURITY].value != nullptr) {
     args->context[GRPC_CONTEXT_SECURITY].destroy(
     args->context[GRPC_CONTEXT_SECURITY].destroy(
         args->context[GRPC_CONTEXT_SECURITY].value);
         args->context[GRPC_CONTEXT_SECURITY].value);

+ 6 - 7
src/core/lib/surface/call.cc

@@ -34,6 +34,7 @@
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/compression/algorithm_metadata.h"
 #include "src/core/lib/compression/algorithm_metadata.h"
 #include "src/core/lib/debug/stats.h"
 #include "src/core/lib/debug/stats.h"
+#include "src/core/lib/gpr/alloc.h"
 #include "src/core/lib/gpr/arena.h"
 #include "src/core/lib/gpr/arena.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"
@@ -271,16 +272,12 @@ struct grpc_call {
 grpc_core::TraceFlag grpc_call_error_trace(false, "call_error");
 grpc_core::TraceFlag grpc_call_error_trace(false, "call_error");
 grpc_core::TraceFlag grpc_compression_trace(false, "compression");
 grpc_core::TraceFlag grpc_compression_trace(false, "compression");
 
 
-/* Given a size, round up to the next multiple of sizeof(void*) */
-#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
-  (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
-
 #define CALL_STACK_FROM_CALL(call)   \
 #define CALL_STACK_FROM_CALL(call)   \
   (grpc_call_stack*)((char*)(call) + \
   (grpc_call_stack*)((char*)(call) + \
-                     ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
+                     GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
 #define CALL_FROM_CALL_STACK(call_stack) \
 #define CALL_FROM_CALL_STACK(call_stack) \
   (grpc_call*)(((char*)(call_stack)) -   \
   (grpc_call*)(((char*)(call_stack)) -   \
-               ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
+               GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
 
 
 #define CALL_ELEM_FROM_CALL(call, idx) \
 #define CALL_ELEM_FROM_CALL(call, idx) \
   grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
   grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
@@ -353,7 +350,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args,
   GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size);
   GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size);
   gpr_arena* arena = gpr_arena_create(initial_size);
   gpr_arena* arena = gpr_arena_create(initial_size);
   call = static_cast<grpc_call*>(
   call = static_cast<grpc_call*>(
-      gpr_arena_alloc(arena, ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) +
+      gpr_arena_alloc(arena, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) +
                                  channel_stack->call_stack_size));
                                  channel_stack->call_stack_size));
   gpr_ref_init(&call->ext_ref, 1);
   gpr_ref_init(&call->ext_ref, 1);
   call->arena = arena;
   call->arena = arena;
@@ -1113,6 +1110,8 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b) {
   publish_app_metadata(call, b, true);
   publish_app_metadata(call, b, true);
 }
 }
 
 
+gpr_arena* grpc_call_get_arena(grpc_call* call) { return call->arena; }
+
 grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) {
 grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) {
   return CALL_STACK_FROM_CALL(call);
   return CALL_STACK_FROM_CALL(call);
 }
 }

+ 2 - 0
src/core/lib/surface/call.h

@@ -71,6 +71,8 @@ void grpc_call_internal_unref(grpc_call* call);
 #define GRPC_CALL_INTERNAL_UNREF(call, reason) grpc_call_internal_unref(call)
 #define GRPC_CALL_INTERNAL_UNREF(call, reason) grpc_call_internal_unref(call)
 #endif
 #endif
 
 
+gpr_arena* grpc_call_get_arena(grpc_call* call);
+
 grpc_call_stack* grpc_call_get_call_stack(grpc_call* call);
 grpc_call_stack* grpc_call_get_call_stack(grpc_call* call);
 
 
 grpc_call_error grpc_call_start_batch_and_execute(grpc_call* call,
 grpc_call_error grpc_call_start_batch_and_execute(grpc_call* call,

+ 2 - 1
src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc

@@ -127,7 +127,8 @@ static tsi_result handshaker_result_create_zero_copy_grpc_protector(
   tsi_result ok = alts_zero_copy_grpc_protector_create(
   tsi_result ok = alts_zero_copy_grpc_protector_create(
       reinterpret_cast<const uint8_t*>(result->key_data),
       reinterpret_cast<const uint8_t*>(result->key_data),
       kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client,
       kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client,
-      /*is_integrity_only=*/false, max_output_protected_frame_size, protector);
+      /*is_integrity_only=*/false, /*enable_extra_copy=*/false,
+      max_output_protected_frame_size, protector);
   if (ok != TSI_OK) {
   if (ok != TSI_OK) {
     gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
     gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
   }
   }

+ 47 - 1
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc

@@ -23,6 +23,8 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 
 
+#include <string.h>
+
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
@@ -30,12 +32,49 @@
 /* Main struct for alts_grpc_integrity_only_record_protocol.  */
 /* Main struct for alts_grpc_integrity_only_record_protocol.  */
 typedef struct alts_grpc_integrity_only_record_protocol {
 typedef struct alts_grpc_integrity_only_record_protocol {
   alts_grpc_record_protocol base;
   alts_grpc_record_protocol base;
+  bool enable_extra_copy;
   grpc_slice_buffer data_sb;
   grpc_slice_buffer data_sb;
   unsigned char* tag_buf;
   unsigned char* tag_buf;
 } alts_grpc_integrity_only_record_protocol;
 } alts_grpc_integrity_only_record_protocol;
 
 
 /* --- alts_grpc_record_protocol methods implementation. --- */
 /* --- alts_grpc_record_protocol methods implementation. --- */
 
 
+static tsi_result alts_grpc_integrity_only_extra_copy_protect(
+    alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
+    grpc_slice_buffer* protected_slices) {
+  /* Allocates memory for protected frame.  */
+  size_t protected_frame_size =
+      unprotected_slices->length + rp->header_length + rp->tag_length;
+  grpc_slice protected_slice = GRPC_SLICE_MALLOC(protected_frame_size);
+  /* Calls alts_iovec_record_protocol protect.  */
+  char* error_details = nullptr;
+  iovec_t header_iovec = {GRPC_SLICE_START_PTR(protected_slice),
+                          rp->header_length};
+  iovec_t tag_iovec = {GRPC_SLICE_START_PTR(protected_slice) +
+                           rp->header_length + unprotected_slices->length,
+                       rp->tag_length};
+  alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
+                                                          unprotected_slices);
+  grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
+      rp->iovec_rp, rp->iovec_buf, unprotected_slices->count, header_iovec,
+      tag_iovec, &error_details);
+  if (status != GRPC_STATUS_OK) {
+    gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
+    gpr_free(error_details);
+    return TSI_INTERNAL_ERROR;
+  }
+  /* Copies data from unprotected_slices to protected_slice.  */
+  uint8_t* data = GRPC_SLICE_START_PTR(protected_slice) + rp->header_length;
+  for (size_t i = 0; i < unprotected_slices->count; i++) {
+    memcpy(data, GRPC_SLICE_START_PTR(unprotected_slices->slices[i]),
+           GRPC_SLICE_LENGTH(unprotected_slices->slices[i]));
+    data += GRPC_SLICE_LENGTH(unprotected_slices->slices[i]);
+  }
+  grpc_slice_buffer_add(protected_slices, protected_slice);
+  grpc_slice_buffer_reset_and_unref_internal(unprotected_slices);
+  return TSI_OK;
+}
+
 static tsi_result alts_grpc_integrity_only_protect(
 static tsi_result alts_grpc_integrity_only_protect(
     alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
     alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
     grpc_slice_buffer* protected_slices) {
     grpc_slice_buffer* protected_slices) {
@@ -46,6 +85,12 @@ static tsi_result alts_grpc_integrity_only_protect(
             "Invalid nullptr arguments to alts_grpc_record_protocol protect.");
             "Invalid nullptr arguments to alts_grpc_record_protocol protect.");
     return TSI_INVALID_ARGUMENT;
     return TSI_INVALID_ARGUMENT;
   }
   }
+  alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol =
+      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
+  if (integrity_only_record_protocol->enable_extra_copy) {
+    return alts_grpc_integrity_only_extra_copy_protect(rp, unprotected_slices,
+                                                       protected_slices);
+  }
   /* Allocates memory for header and tag slices.  */
   /* Allocates memory for header and tag slices.  */
   grpc_slice header_slice = GRPC_SLICE_MALLOC(rp->header_length);
   grpc_slice header_slice = GRPC_SLICE_MALLOC(rp->header_length);
   grpc_slice tag_slice = GRPC_SLICE_MALLOC(rp->tag_length);
   grpc_slice tag_slice = GRPC_SLICE_MALLOC(rp->tag_length);
@@ -152,7 +197,7 @@ static const alts_grpc_record_protocol_vtable
 
 
 tsi_result alts_grpc_integrity_only_record_protocol_create(
 tsi_result alts_grpc_integrity_only_record_protocol_create(
     gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
     gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
-    bool is_protect, alts_grpc_record_protocol** rp) {
+    bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** rp) {
   if (crypter == nullptr || rp == nullptr) {
   if (crypter == nullptr || rp == nullptr) {
     gpr_log(GPR_ERROR,
     gpr_log(GPR_ERROR,
             "Invalid nullptr arguments to alts_grpc_record_protocol create.");
             "Invalid nullptr arguments to alts_grpc_record_protocol create.");
@@ -169,6 +214,7 @@ tsi_result alts_grpc_integrity_only_record_protocol_create(
     gpr_free(impl);
     gpr_free(impl);
     return result;
     return result;
   }
   }
+  impl->enable_extra_copy = enable_extra_copy;
   /* Initializes slice buffer for data_sb.  */
   /* Initializes slice buffer for data_sb.  */
   grpc_slice_buffer_init(&impl->data_sb);
   grpc_slice_buffer_init(&impl->data_sb);
   /* Allocates tag buffer.  */
   /* Allocates tag buffer.  */

+ 3 - 1
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h

@@ -38,6 +38,8 @@
  *   be used at the client or server side.
  *   be used at the client or server side.
  * - is_protect: a flag indicating if the alts_grpc_record_protocol instance
  * - is_protect: a flag indicating if the alts_grpc_record_protocol instance
  *   will be used for protect or unprotect.
  *   will be used for protect or unprotect.
+ *-  enable_extra_copy: a flag indicating if the instance uses one-copy instead
+ *   of zero-copy in the protect operation.
  * - rp: an alts_grpc_record_protocol instance to be returned from
  * - rp: an alts_grpc_record_protocol instance to be returned from
  *   the method.
  *   the method.
  *
  *
@@ -46,7 +48,7 @@
  */
  */
 tsi_result alts_grpc_integrity_only_record_protocol_create(
 tsi_result alts_grpc_integrity_only_record_protocol_create(
     gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
     gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
-    bool is_protect, alts_grpc_record_protocol** rp);
+    bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** rp);
 
 
 #endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_INTEGRITY_ONLY_RECORD_PROTOCOL_H \
 #endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_INTEGRITY_ONLY_RECORD_PROTOCOL_H \
         */
         */

+ 12 - 11
src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc

@@ -110,7 +110,7 @@ static bool read_frame_size(const grpc_slice_buffer* sb,
  */
  */
 static tsi_result create_alts_grpc_record_protocol(
 static tsi_result create_alts_grpc_record_protocol(
     const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
     const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
-    bool is_integrity_only, bool is_protect,
+    bool is_integrity_only, bool is_protect, bool enable_extra_copy,
     alts_grpc_record_protocol** record_protocol) {
     alts_grpc_record_protocol** record_protocol) {
   if (key == nullptr || record_protocol == nullptr) {
   if (key == nullptr || record_protocol == nullptr) {
     return TSI_INVALID_ARGUMENT;
     return TSI_INVALID_ARGUMENT;
@@ -130,13 +130,13 @@ static tsi_result create_alts_grpc_record_protocol(
                                    : kAltsRecordProtocolFrameLimit;
                                    : kAltsRecordProtocolFrameLimit;
   /* Creates alts_grpc_record_protocol with AEAD crypter ownership transferred.
   /* Creates alts_grpc_record_protocol with AEAD crypter ownership transferred.
    */
    */
-  tsi_result result =
-      is_integrity_only
-          ? alts_grpc_integrity_only_record_protocol_create(
-                crypter, overflow_limit, is_client, is_protect, record_protocol)
-          : alts_grpc_privacy_integrity_record_protocol_create(
-                crypter, overflow_limit, is_client, is_protect,
-                record_protocol);
+  tsi_result result = is_integrity_only
+                          ? alts_grpc_integrity_only_record_protocol_create(
+                                crypter, overflow_limit, is_client, is_protect,
+                                enable_extra_copy, record_protocol)
+                          : alts_grpc_privacy_integrity_record_protocol_create(
+                                crypter, overflow_limit, is_client, is_protect,
+                                record_protocol);
   if (result != TSI_OK) {
   if (result != TSI_OK) {
     gsec_aead_crypter_destroy(crypter);
     gsec_aead_crypter_destroy(crypter);
     return result;
     return result;
@@ -241,7 +241,8 @@ static const tsi_zero_copy_grpc_protector_vtable
 
 
 tsi_result alts_zero_copy_grpc_protector_create(
 tsi_result alts_zero_copy_grpc_protector_create(
     const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
     const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
-    bool is_integrity_only, size_t* max_protected_frame_size,
+    bool is_integrity_only, bool enable_extra_copy,
+    size_t* max_protected_frame_size,
     tsi_zero_copy_grpc_protector** protector) {
     tsi_zero_copy_grpc_protector** protector) {
   if (grpc_core::ExecCtx::Get() == nullptr || key == nullptr ||
   if (grpc_core::ExecCtx::Get() == nullptr || key == nullptr ||
       protector == nullptr) {
       protector == nullptr) {
@@ -257,11 +258,11 @@ tsi_result alts_zero_copy_grpc_protector_create(
   /* Creates alts_grpc_record_protocol objects.  */
   /* Creates alts_grpc_record_protocol objects.  */
   tsi_result status = create_alts_grpc_record_protocol(
   tsi_result status = create_alts_grpc_record_protocol(
       key, key_size, is_rekey, is_client, is_integrity_only,
       key, key_size, is_rekey, is_client, is_integrity_only,
-      /*is_protect=*/true, &impl->record_protocol);
+      /*is_protect=*/true, enable_extra_copy, &impl->record_protocol);
   if (status == TSI_OK) {
   if (status == TSI_OK) {
     status = create_alts_grpc_record_protocol(
     status = create_alts_grpc_record_protocol(
         key, key_size, is_rekey, is_client, is_integrity_only,
         key, key_size, is_rekey, is_client, is_integrity_only,
-        /*is_protect=*/false, &impl->unrecord_protocol);
+        /*is_protect=*/false, enable_extra_copy, &impl->unrecord_protocol);
     if (status == TSI_OK) {
     if (status == TSI_OK) {
       /* Sets maximum frame size.  */
       /* Sets maximum frame size.  */
       size_t max_protected_frame_size_to_set = kDefaultFrameLength;
       size_t max_protected_frame_size_to_set = kDefaultFrameLength;

+ 7 - 2
src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h

@@ -35,6 +35,11 @@
  *   server side.
  *   server side.
  * - is_integrity_only: a flag indicating if the protector instance will be
  * - is_integrity_only: a flag indicating if the protector instance will be
  *   used for integrity-only or privacy-integrity mode.
  *   used for integrity-only or privacy-integrity mode.
+ * - enable_extra_copy: a flag indicating if the protector instance does one
+ *   extra memory copy during the protect operation for integrity_only mode.
+ *   For the unprotect operation, it is still zero-copy. If application intends
+ *   to modify the data buffer after the protect operation, we can turn on this
+ *   mode to avoid integrity check failure.
  * - max_protected_frame_size: an in/out parameter indicating max frame size
  * - max_protected_frame_size: an in/out parameter indicating max frame size
  *   to be used by the protector. If it is nullptr, the default frame size will
  *   to be used by the protector. If it is nullptr, the default frame size will
  *   be used. Otherwise, the provided frame size will be adjusted (if not
  *   be used. Otherwise, the provided frame size will be adjusted (if not
@@ -45,8 +50,8 @@
  */
  */
 tsi_result alts_zero_copy_grpc_protector_create(
 tsi_result alts_zero_copy_grpc_protector_create(
     const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
     const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
-    bool is_integrity_only, size_t* max_protected_frame_size,
-    tsi_zero_copy_grpc_protector** protector);
+    bool is_integrity_only, bool enable_extra_copy,
+    size_t* max_protected_frame_size, tsi_zero_copy_grpc_protector** protector);
 
 
 #endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_ZERO_COPY_GRPC_PROTECTOR_H \
 #endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_ZERO_COPY_GRPC_PROTECTOR_H \
         */
         */

+ 15 - 0
src/objective-c/GRPCClient/GRPCCall+ChannelArg.h

@@ -55,4 +55,19 @@ typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) {
                          timeout:(int)timeout
                          timeout:(int)timeout
                          forHost:(nonnull NSString *)host;
                          forHost:(nonnull NSString *)host;
 
 
+/** Enable/Disable automatic retry of gRPC calls on the channel. If automatic retry is enabled, the
+ * retry is controlled by server's service config. If automatic retry is disabled, failed calls are
+ * immediately returned to the application layer. */
++ (void)enableRetry:(BOOL)enabled forHost:(nonnull NSString *)host;
+
+/** Set channel connection timeout and backoff parameters. All parameters are positive integers in
+ * milliseconds. Set a parameter to 0 to make gRPC use default value for that parameter.
+ *
+ * Refer to gRPC's doc at https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md for the
+ * details of each parameter. */
++ (void)setMinConnectTimeout:(unsigned int)timeout
+              initialBackoff:(unsigned int)initialBackoff
+                  maxBackoff:(unsigned int)maxBackoff
+                     forHost:(nonnull NSString *)host;
+
 @end
 @end

+ 15 - 0
src/objective-c/GRPCClient/GRPCCall+ChannelArg.m

@@ -64,4 +64,19 @@
   hostConfig.keepaliveTimeout = timeout;
   hostConfig.keepaliveTimeout = timeout;
 }
 }
 
 
++ (void)enableRetry:(BOOL)enabled forHost:(nonnull NSString *)host {
+  GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
+  hostConfig.retryEnabled = enabled;
+}
+
++ (void)setMinConnectTimeout:(unsigned int)timeout
+              initialBackoff:(unsigned int)initialBackoff
+                  maxBackoff:(unsigned int)maxBackoff
+                     forHost:(nonnull NSString *)host {
+  GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
+  hostConfig.minConnectTimeout = timeout;
+  hostConfig.initialConnectBackoff = initialBackoff;
+  hostConfig.maxConnectBackoff = maxBackoff;
+}
+
 @end
 @end

+ 5 - 0
src/objective-c/GRPCClient/private/GRPCHost.h

@@ -38,6 +38,11 @@ struct grpc_channel_credentials;
 @property(nonatomic) int keepaliveInterval;
 @property(nonatomic) int keepaliveInterval;
 @property(nonatomic) int keepaliveTimeout;
 @property(nonatomic) int keepaliveTimeout;
 @property(nonatomic) id logContext;
 @property(nonatomic) id logContext;
+@property(nonatomic) BOOL retryEnabled;
+
+@property(nonatomic) unsigned int minConnectTimeout;
+@property(nonatomic) unsigned int initialConnectBackoff;
+@property(nonatomic) unsigned int maxConnectBackoff;
 
 
 /** The following properties should only be modified for testing: */
 /** The following properties should only be modified for testing: */
 
 

+ 15 - 0
src/objective-c/GRPCClient/private/GRPCHost.m

@@ -85,6 +85,7 @@ static NSMutableDictionary *kHostCache;
       _secure = YES;
       _secure = YES;
       kHostCache[address] = self;
       kHostCache[address] = self;
       _compressAlgorithm = GRPC_COMPRESS_NONE;
       _compressAlgorithm = GRPC_COMPRESS_NONE;
+      _retryEnabled = YES;
     }
     }
 #ifndef GRPC_CFSTREAM
 #ifndef GRPC_CFSTREAM
     [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChange:)];
     [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChange:)];
@@ -240,6 +241,20 @@ static NSMutableDictionary *kHostCache;
     args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1];
     args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1];
   }
   }
 
 
+  if (_retryEnabled == NO) {
+    args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:0];
+  }
+
+  if (_minConnectTimeout > 0) {
+    args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_minConnectTimeout];
+  }
+  if (_initialConnectBackoff > 0) {
+    args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_initialConnectBackoff];
+  }
+  if (_maxConnectBackoff > 0) {
+    args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_maxConnectBackoff];
+  }
+
   return args;
   return args;
 }
 }
 
 

+ 92 - 0
src/objective-c/NetworkTransitionBehavior.md

@@ -0,0 +1,92 @@
+
+# gRPC iOS Network Transition Behaviors
+Network connectivity on an iOS device may transition between cellular, WIFI, or
+no network connectivity. This document describes how these network changes
+should be handled by gRPC and current known issues.
+
+## Expected Network Transition Behaviors
+The expected gRPC iOS channel and network transition behaviors are:
+* Channel connection to a particular host is established at the time of
+  starting the first call to the channel and remains connected for future calls
+  to the same host.
+* If the underlying connection to the remote host is broken, the channel is
+  disconnected and enters TRANSIENT\_FAILURE state.
+* A channel is broken if the channel connection is no longer viable. This
+  happens when
+    * The network interface is no longer available, e.g. WiFi or cellular
+      interface is turned off or goes offline, airplane mode turned on, etc;
+    * The underlying TCP connection is no longer valid, e.g. WiFi connects to
+      another hotspot, cellular data switched from LTE to 4G, etc;
+    * A network interface more preferable by the OS is valid, e.g. WiFi gets
+      connected when the channel is already connected via cellular.
+* A channel in TRANSIENT\_FAILURE state attempts reconnection on start of the
+  next call to the same host, but only after a certain backoff period (see
+  corresponding
+  [doc](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)).
+  During the backoff period, any call to the same host will wait until the
+  first of the following events occur:
+    * Connection succeeded; calls will be made using this channel;
+    * Conncetion failed; calls will be failed and return UNAVAILABLE status code;
+    * The call's deadline is reached; the call will fail and return
+      DEADLINE\_EXCEEDED status code.
+  The length of backoff period of a channel is reset whenever a connection
+  attempt is successful.
+
+## Implementations
+### gRPC iOS with TCP Sockets
+gRPC's default implementation is to use TCP sockets for networking. It turns
+out that although Apple supports this type of usage, it is [not recommended by
+Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html)
+and has some issues described below.
+
+#### Issues with TCP Sockets
+The TCP sockets on iOS is flawed in that it does not reflect the viability of
+the channel connection. Particularly, we observed the following issues when
+using TCP sockets:
+* When a TCP socket connection is established on cellular data and WiFi
+  becomes available, the TCP socket neither return an error event nor continue
+  sending/receiving data on it, but still accepts write on it.
+* A TCP socket does not report certain events that happen in the
+  background. When a TCP connection breaks in the background for the reason
+  like WiFi connects to another hotspot, the socket neither return an error nor
+  continue sending/receiving data on it, but still accepts write on it.
+In both situations, the user will see the call hang for an extended period of
+time before the TCP socket times out.
+
+#### gRPC iOS library's resolution to TCP socket issues
+We introduced
+[`ConnectivityMonitor`](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html)
+in gRPC iOS library v0.14.0 to alleviate these issues in TCP sockets,
+which changes the network transition behaviors a bit.
+
+We classify network connectivity state of the device into three categories
+based on flags obtained from `SCNetworkReachability` API:
+
+| Reachable | ConnectionRequired | IsWWAN | **Category** |
+|:---------:|:------------------:|:------:|:------------:|
+|     0     |          X         |   X    |     None     |
+|     X     |          1         |   X    |     None     |
+|     1     |          0         |   0    |     WiFi     |
+|     1     |          0         |   1    |   Cellular   |
+
+Whenever there is a transition of network between two of these categories, all
+previously existing channels are assumed to be broken and are actively
+destroyed. If there is an unfinished call, the call should return with status
+code `UNAVAILABLE`.
+
+`ConnectivityMonitor` is able to detect the scenario of the first issue above
+and actively destroy the channels. However, the second issue is not resolvable.
+To solve that issue the best solution is to switch to CFStream implementation
+which eliminates all of them.
+
+### gRPC iOS with CFStream
+gRPC iOS with CFStream implementation (introduced in v1.13.0) uses Apple's
+networking API to make connections. It resolves the issues with TCP sockets
+mentioned above. Users are recommended to use this implementation rather than
+TCP socket implementation. The detailed behavior of streams in CFStream is not
+documented by Apple, but our experiments show that it accords to the expected
+behaviors.  With CFStream implementation, an event is always received when the
+underlying connection is no longer viable. For more detailed information and
+usages of CFStream implementation, refer to the
+[user guide](https://github.com/grpc/grpc/blob/master/src/objective-c/README-CFSTREAM.md).
+

+ 32 - 0
src/objective-c/README-CFSTREAM.md

@@ -0,0 +1,32 @@
+[![Cocoapods](https://img.shields.io/cocoapods/v/gRPC.svg)](https://cocoapods.org/pods/gRPC)
+# gRPC Objective-C with CFStream
+
+gRPC Objective-C library now provides the option to use Apple's CFStream API (rather than TCP
+sockets) for networking. Using CFStream resolves a bunch of network connectivity transition issues
+(see the [doc](https://github.com/grpc/grpc/blob/master/src/objective-c/NetworkTransitionBehavior.md)
+for more information).
+
+CFStream integration is now in experimental state. You will need explicit opt-in to use it to get
+the benefits of resolving the issues above. We expect to make CFStream the default networking
+interface that gRPC uses when it is ready for production.
+
+## Usage
+If you use gRPC following the instructions in
+[README.md](https://github.com/grpc/grpc/blob/master/src/objective-c/README.md):
+- Simply replace the
+dependency on `gRPC-ProtoRPC` with `gRPC-ProtoRPC/CFStream`. The build system will take care of
+everything else and switch networking to CFStream.
+
+If your project directly depends on podspecs other than `gRPC-ProtoRPC` (e.g. `gRPC` or
+`gRPC-Core`):
+
+- Make your projects depend on subspecs corresponding to CFStream in each gRPC podspec. For
+  `gRPC-Core`, you will need to make sure that the completion queue you create is of type
+  `GRPC_CQ_NON_POLLING`. This is expected to be fixed soon so that you do not have to modify the
+  completion queue type.
+
+## Notes
+
+- Currently we do not support platforms other than iOS, although it is likely that this integration
+  can run on MacOS targets with Apple's compiler.
+- Let us know if you meet any issue by filing issue and ping @muxi.

+ 43 - 0
src/objective-c/tests/GRPCClientTests.m

@@ -548,4 +548,47 @@ static GRPCProtoMethod *kFullDuplexCallMethod;
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 }
 
 
+- (void)testTimeoutBackoffWithTimeout:(double)timeout Backoff:(double)backoff {
+  const double maxConnectTime = timeout > backoff ? timeout : backoff;
+  const double kMargin = 0.1;
+
+  __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."];
+  NSString *const kDummyAddress = [NSString stringWithFormat:@"8.8.8.8:1"];
+  GRPCCall *call = [[GRPCCall alloc] initWithHost:kDummyAddress
+                                             path:@""
+                                   requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
+  [GRPCCall setMinConnectTimeout:timeout * 1000
+                  initialBackoff:backoff * 1000
+                      maxBackoff:0
+                         forHost:kDummyAddress];
+  NSDate *startTime = [NSDate date];
+  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) {
+    XCTAssert(NO, @"Received message. Should not reach here");
+  }
+      completionHandler:^(NSError *errorOrNil) {
+        XCTAssertNotNil(errorOrNil, @"Finished with no error");
+        // The call must fail before maxConnectTime. However there is no lower bound on the time
+        // taken for connection. A shorter time happens when connection is actively refused
+        // by 8.8.8.8:1 before maxConnectTime elapsed.
+        XCTAssertLessThan([[NSDate date] timeIntervalSinceDate:startTime],
+                          maxConnectTime + kMargin);
+        [completion fulfill];
+      }];
+
+  [call startWithWriteable:responsesWriteable];
+
+  [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+}
+
+// The numbers of the following three tests are selected to be smaller than the default values of
+// initial backoff (1s) and min_connect_timeout (20s), so that if they fail we know the default
+// values fail to be overridden by the channel args.
+- (void)testTimeoutBackoff2 {
+  [self testTimeoutBackoffWithTimeout:0.7 Backoff:0.3];
+}
+
+- (void)testTimeoutBackoff3 {
+  [self testTimeoutBackoffWithTimeout:0.3 Backoff:0.7];
+}
+
 @end
 @end

+ 13 - 2
templates/Makefile.template

@@ -37,10 +37,10 @@
 
 
     # warnings we'd like, but that dont exist in all compilers
     # warnings we'd like, but that dont exist in all compilers
     PREFERRED_WARNINGS=['shadow', 'extra-semi']
     PREFERRED_WARNINGS=['shadow', 'extra-semi']
-    CHECK_WARNINGS=PREFERRED_WARNINGS + ['no-shift-negative-value']
+    CHECK_WARNINGS=PREFERRED_WARNINGS + ['no-shift-negative-value', 'no-unused-but-set-variable', 'no-maybe-uninitialized']
 
 
     def warning_var(fmt, warning):
     def warning_var(fmt, warning):
-      return fmt % warning.replace('-', '_').upper()
+      return fmt % warning.replace('-', '_').replace('+', 'X').upper()
 
 
     def neg_warning(warning):
     def neg_warning(warning):
       if warning[0:3] == 'no-':
       if warning[0:3] == 'no-':
@@ -191,6 +191,12 @@
   TMPOUT = `mktemp /tmp/test-out-XXXXXX`
   TMPOUT = `mktemp /tmp/test-out-XXXXXX`
   endif
   endif
 
 
+  CHECK_NO_CXX14_COMPAT_WORKS_CMD = $(CC) -std=c++11 -Werror -Wno-c++14-compat -o $(TMPOUT) -c test/build/no-c++14-compat.cc
+  HAS_WORKING_NO_CXX14_COMPAT = $(shell $(CHECK_NO_CXX14_COMPAT_WORKS_CMD) 2> /dev/null && echo true || echo false)
+  ifeq ($(HAS_WORKING_NO_CXX14_COMPAT),true)
+  W_NO_CXX14_COMPAT=-Wno-c++14-compat
+  endif
+
   %for warning in CHECK_WARNINGS:
   %for warning in CHECK_WARNINGS:
   ${warning_var('CHECK_%s_WORKS_CMD', warning)} = $(CC) -std=c99 -Werror -W${warning} -o $(TMPOUT) -c test/build/${warning}.c
   ${warning_var('CHECK_%s_WORKS_CMD', warning)} = $(CC) -std=c99 -Werror -W${warning} -o $(TMPOUT) -c test/build/${warning}.c
   ${warning_var('HAS_WORKING_%s', warning)} = $(shell $(${warning_var('CHECK_%s_WORKS_CMD', warning)}) 2> /dev/null && echo true || echo false)
   ${warning_var('HAS_WORKING_%s', warning)} = $(shell $(${warning_var('CHECK_%s_WORKS_CMD', warning)}) 2> /dev/null && echo true || echo false)
@@ -1271,6 +1277,11 @@
   	$(Q) mkdir -p `dirname $@`
   	$(Q) mkdir -p `dirname $@`
   	$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
   	$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
 
 
+  $(OBJDIR)/$(CONFIG)/%.o : %.cpp
+  	$(E) "[CXX]     Compiling $<"
+  	$(Q) mkdir -p `dirname $@`
+  	$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
+
   install: install_c install_cxx install-plugins install-certs
   install: install_c install_cxx install-plugins install-certs
 
 
   install_c: install-headers_c install-static_c install-shared_c
   install_c: install-headers_c install-static_c install-shared_c

+ 9 - 1
templates/gRPC-C++.podspec.template

@@ -49,6 +49,7 @@
     out = grpc_lib_files(filegroups, ("grpc++_codegen_proto", "grpc++_config_proto"), ("headers", "src", "public_headers"))
     out = grpc_lib_files(filegroups, ("grpc++_codegen_proto", "grpc++_config_proto"), ("headers", "src", "public_headers"))
     excl_files = grpc_lib_files(filegroups, ("grpc++_codegen_base",), ("headers", "src", "public_headers"))
     excl_files = grpc_lib_files(filegroups, ("grpc++_codegen_base",), ("headers", "src", "public_headers"))
     out = [file for file in out if file not in excl_files]
     out = [file for file in out if file not in excl_files]
+    out = filter_grpcpp(out)
     return out
     return out
 
 
   def grpcpp_private_files(libs, filegroups):
   def grpcpp_private_files(libs, filegroups):
@@ -131,7 +132,7 @@
     s.name     = 'gRPC-C++'
     s.name     = 'gRPC-C++'
     # TODO (mxyan): use version that match gRPC version when pod is stabilized
     # TODO (mxyan): use version that match gRPC version when pod is stabilized
     # version = '${settings.version}'
     # version = '${settings.version}'
-    version = '0.0.2'
+    version = '0.0.3'
     s.version  = version
     s.version  = version
     s.summary  = 'gRPC C++ library'
     s.summary  = 'gRPC C++ library'
     s.homepage = 'https://grpc.io'
     s.homepage = 'https://grpc.io'
@@ -195,6 +196,13 @@
       ss.private_header_files = ${ruby_multiline_list(grpcpp_private_headers(libs, filegroups), 30)}
       ss.private_header_files = ${ruby_multiline_list(grpcpp_private_headers(libs, filegroups), 30)}
     end
     end
 
 
+    s.subspec 'Protobuf' do |ss|
+      ss.header_mappings_dir = 'include/grpcpp'
+      ss.dependency "#{s.name}/Interface", version
+
+      ss.source_files = ${ruby_multiline_list(grpcpp_proto_files(filegroups), 22)}
+    end
+
     s.prepare_command = <<-END_OF_COMMAND
     s.prepare_command = <<-END_OF_COMMAND
       find src/cpp/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
       find src/cpp/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
       find src/cpp/ -type f -path '*.grpc_back' -print0 | xargs -0 rm
       find src/cpp/ -type f -path '*.grpc_back' -print0 | xargs -0 rm

+ 19 - 0
test/build/no-c++14-compat.cc

@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+int main(void) {}

+ 19 - 0
test/build/no-maybe-uninitialized.c

@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+int main(void) {}

+ 19 - 0
test/build/no-unused-but-set-variable.c

@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+int main(void) {}

+ 18 - 3
test/core/iomgr/BUILD

@@ -18,7 +18,10 @@ licenses(["notice"])  # Apache v2
 
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 
-grpc_package(name = "test/core/iomgr", visibility = "public") # Useful for third party devs to test their io manager implementation.
+grpc_package(
+    name = "test/core/iomgr",
+    visibility = "public",
+)  # Useful for third party devs to test their io manager implementation.
 
 
 grpc_cc_library(
 grpc_cc_library(
     name = "endpoint_tests",
     name = "endpoint_tests",
@@ -72,16 +75,28 @@ grpc_cc_test(
     ],
     ],
 )
 )
 
 
+grpc_cc_test(
+    name = "ev_epollex_linux_test",
+    srcs = ["ev_epollex_linux_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 = "ev_epollsig_linux_test",
     name = "ev_epollsig_linux_test",
     srcs = ["ev_epollsig_linux_test.cc"],
     srcs = ["ev_epollsig_linux_test.cc"],
+    language = "C++",
     deps = [
     deps = [
         "//:gpr",
         "//:gpr",
         "//:grpc",
         "//:grpc",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
         "//test/core/util:grpc_test_util",
     ],
     ],
-    language = "C++",
 )
 )
 
 
 grpc_cc_test(
 grpc_cc_test(
@@ -221,13 +236,13 @@ 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"],
     language = "C++",
     language = "C++",
+    tags = ["manual"],  # TODO(adelez): Remove once this works on Foundry.
     deps = [
     deps = [
         "//:gpr",
         "//:gpr",
         "//:grpc",
         "//:grpc",
         "//test/core/util:gpr_test_util",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
         "//test/core/util:grpc_test_util",
     ],
     ],
-    tags = ["manual"],    # TODO(adelez): Remove once this works on Foundry.
 )
 )
 
 
 grpc_cc_test(
 grpc_cc_test(

+ 115 - 0
test/core/iomgr/ev_epollex_linux_test.cc

@@ -0,0 +1,115 @@
+/*
+ *
+ * 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"
+
+/* This test only relevant on linux systems where epoll() is available */
+#if defined(GRPC_LINUX_EPOLL_CREATE1) && defined(GRPC_LINUX_EVENTFD)
+#include "src/core/lib/iomgr/ev_epollex_linux.h"
+
+#include <grpc/grpc.h>
+#include <string.h>
+#include <sys/eventfd.h>
+
+#include "test/core/util/test_config.h"
+
+static void pollset_destroy(void* ps, grpc_error* error) {
+  grpc_pollset_destroy(static_cast<grpc_pollset*>(ps));
+  gpr_free(ps);
+}
+
+// This test is added to cover the case found in bug:
+// https://github.com/grpc/grpc/issues/15760
+static void test_pollable_owner_fd() {
+  grpc_core::ExecCtx exec_ctx;
+  int ev_fd1;
+  int ev_fd2;
+  grpc_fd* grpc_fd1;
+  grpc_fd* grpc_fd2;
+  grpc_pollset* ps;
+  gpr_mu* mu;
+
+  // == Create two grpc_fds ==
+  // All we need is two file descriptors. Doesn't matter what type. We use
+  // eventfd type here for the purpose of this test
+  ev_fd1 = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+  ev_fd2 = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+  if (ev_fd1 < 0 || ev_fd2 < 0) {
+    gpr_log(GPR_ERROR, "Error in creating event fds for the test");
+    return;
+  }
+  grpc_fd1 = grpc_fd_create(ev_fd1, "epollex-test-fd1", false);
+  grpc_fd2 = grpc_fd_create(ev_fd2, "epollex-test-fd2", false);
+  grpc_core::ExecCtx::Get()->Flush();
+
+  // == Create a pollset ==
+  ps = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
+  grpc_pollset_init(ps, &mu);
+  grpc_core::ExecCtx::Get()->Flush();
+
+  // == Add fd1 to pollset ==
+  grpc_pollset_add_fd(ps, grpc_fd1);
+  grpc_core::ExecCtx::Get()->Flush();
+
+  // == Destroy fd1 ==
+  grpc_fd_orphan(grpc_fd1, nullptr, nullptr, "test fd1 orphan");
+  grpc_core::ExecCtx::Get()->Flush();
+
+  // = Add fd2 to pollset ==
+  //
+  // Before https://github.com/grpc/grpc/issues/15760, the following line caused
+  // unexpected behavior (The previous grpc_pollset_add_fd(ps, grpc_fd1) created
+  // an underlying structure in epollex that held a reference to grpc_fd1 which
+  // was being accessed here even after grpc_fd_orphan(grpc_fd1) was called
+  grpc_pollset_add_fd(ps, grpc_fd2);
+  grpc_core::ExecCtx::Get()->Flush();
+
+  // == Destroy fd2 ==
+  grpc_fd_orphan(grpc_fd2, nullptr, nullptr, "test fd2 orphan");
+  grpc_core::ExecCtx::Get()->Flush();
+
+  // == Destroy pollset
+  grpc_closure ps_destroy_closure;
+  GRPC_CLOSURE_INIT(&ps_destroy_closure, pollset_destroy, ps,
+                    grpc_schedule_on_exec_ctx);
+  grpc_pollset_shutdown(ps, &ps_destroy_closure);
+  grpc_core::ExecCtx::Get()->Flush();
+}
+
+int main(int argc, char** argv) {
+  const char* poll_strategy = nullptr;
+  grpc_test_init(argc, argv);
+  grpc_init();
+  {
+    grpc_core::ExecCtx exec_ctx;
+    poll_strategy = grpc_get_poll_strategy_name();
+    if (poll_strategy != nullptr && strcmp(poll_strategy, "epollex") == 0) {
+      test_pollable_owner_fd();
+    } else {
+      gpr_log(GPR_INFO,
+              "Skipping the test. The test is only relevant for 'epollex' "
+              "strategy. and the current strategy is: '%s'",
+              poll_strategy);
+    }
+  }
+
+  grpc_shutdown();
+  return 0;
+}
+#else /* defined(GRPC_LINUX_EPOLL_CREATE1) && defined(GRPC_LINUX_EVENTFD) */
+int main(int argc, char** argv) { return 0; }
+#endif

+ 1 - 0
test/core/surface/public_headers_must_be_c89.c

@@ -40,6 +40,7 @@
 #include <grpc/impl/codegen/sync.h>
 #include <grpc/impl/codegen/sync.h>
 #include <grpc/impl/codegen/sync_custom.h>
 #include <grpc/impl/codegen/sync_custom.h>
 #include <grpc/impl/codegen/sync_generic.h>
 #include <grpc/impl/codegen/sync_generic.h>
+#include <grpc/load_reporting.h>
 #include <grpc/slice.h>
 #include <grpc/slice.h>
 #include <grpc/slice_buffer.h>
 #include <grpc/slice_buffer.h>
 #include <grpc/status.h>
 #include <grpc/status.h>

+ 17 - 9
test/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_test.cc

@@ -109,7 +109,7 @@ static void alter_random_byte(grpc_slice_buffer* sb) {
 }
 }
 
 
 static alts_grpc_record_protocol_test_fixture*
 static alts_grpc_record_protocol_test_fixture*
-test_fixture_integrity_only_create(bool rekey) {
+test_fixture_integrity_only_create(bool rekey, bool extra_copy) {
   alts_grpc_record_protocol_test_fixture* fixture =
   alts_grpc_record_protocol_test_fixture* fixture =
       static_cast<alts_grpc_record_protocol_test_fixture*>(
       static_cast<alts_grpc_record_protocol_test_fixture*>(
           gpr_zalloc(sizeof(alts_grpc_record_protocol_test_fixture)));
           gpr_zalloc(sizeof(alts_grpc_record_protocol_test_fixture)));
@@ -124,41 +124,46 @@ test_fixture_integrity_only_create(bool rekey) {
                  &crypter, nullptr) == GRPC_STATUS_OK);
                  &crypter, nullptr) == GRPC_STATUS_OK);
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
                  crypter, 8, /*is_client=*/true, /*is_protect=*/true,
                  crypter, 8, /*is_client=*/true, /*is_protect=*/true,
-                 &fixture->client_protect) == TSI_OK);
+                 extra_copy, &fixture->client_protect) == TSI_OK);
   /* Create client record protocol for unprotect.  */
   /* Create client record protocol for unprotect.  */
   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
                  &crypter, nullptr) == GRPC_STATUS_OK);
                  &crypter, nullptr) == GRPC_STATUS_OK);
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
                  crypter, 8, /*is_client=*/true, /*is_protect=*/false,
                  crypter, 8, /*is_client=*/true, /*is_protect=*/false,
-                 &fixture->client_unprotect) == TSI_OK);
+                 extra_copy, &fixture->client_unprotect) == TSI_OK);
   /* Create server record protocol for protect.  */
   /* Create server record protocol for protect.  */
   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
                  &crypter, nullptr) == GRPC_STATUS_OK);
                  &crypter, nullptr) == GRPC_STATUS_OK);
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
                  crypter, 8, /*is_client=*/false, /*is_protect=*/true,
                  crypter, 8, /*is_client=*/false, /*is_protect=*/true,
-                 &fixture->server_protect) == TSI_OK);
+                 extra_copy, &fixture->server_protect) == TSI_OK);
   /* Create server record protocol for unprotect.  */
   /* Create server record protocol for unprotect.  */
   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
                  &crypter, nullptr) == GRPC_STATUS_OK);
                  &crypter, nullptr) == GRPC_STATUS_OK);
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
   GPR_ASSERT(alts_grpc_integrity_only_record_protocol_create(
                  crypter, 8, /*is_client=*/false, /*is_protect=*/false,
                  crypter, 8, /*is_client=*/false, /*is_protect=*/false,
-                 &fixture->server_unprotect) == TSI_OK);
+                 extra_copy, &fixture->server_unprotect) == TSI_OK);
 
 
   gpr_free(key);
   gpr_free(key);
   return fixture;
   return fixture;
 }
 }
 
 
 static alts_grpc_record_protocol_test_fixture*
 static alts_grpc_record_protocol_test_fixture*
-test_fixture_integrity_only_no_rekey_create() {
-  return test_fixture_integrity_only_create(false);
+test_fixture_integrity_only_no_rekey_no_extra_copy_create() {
+  return test_fixture_integrity_only_create(false, false);
 }
 }
 
 
 static alts_grpc_record_protocol_test_fixture*
 static alts_grpc_record_protocol_test_fixture*
 test_fixture_integrity_only_rekey_create() {
 test_fixture_integrity_only_rekey_create() {
-  return test_fixture_integrity_only_create(true);
+  return test_fixture_integrity_only_create(true, false);
+}
+
+static alts_grpc_record_protocol_test_fixture*
+test_fixture_integrity_only_extra_copy_create() {
+  return test_fixture_integrity_only_create(false, true);
 }
 }
 
 
 static alts_grpc_record_protocol_test_fixture*
 static alts_grpc_record_protocol_test_fixture*
@@ -440,8 +445,11 @@ static void alts_grpc_record_protocol_tests(
 }
 }
 
 
 int main(int argc, char** argv) {
 int main(int argc, char** argv) {
-  alts_grpc_record_protocol_tests(&test_fixture_integrity_only_no_rekey_create);
+  alts_grpc_record_protocol_tests(
+      &test_fixture_integrity_only_no_rekey_no_extra_copy_create);
   alts_grpc_record_protocol_tests(&test_fixture_integrity_only_rekey_create);
   alts_grpc_record_protocol_tests(&test_fixture_integrity_only_rekey_create);
+  alts_grpc_record_protocol_tests(
+      &test_fixture_integrity_only_extra_copy_create);
   alts_grpc_record_protocol_tests(
   alts_grpc_record_protocol_tests(
       &test_fixture_privacy_integrity_no_rekey_create);
       &test_fixture_privacy_integrity_no_rekey_create);
   alts_grpc_record_protocol_tests(&test_fixture_privacy_integrity_rekey_create);
   alts_grpc_record_protocol_tests(&test_fixture_privacy_integrity_rekey_create);

+ 26 - 15
test/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector_test.cc

@@ -100,7 +100,8 @@ static bool are_slice_buffers_equal(grpc_slice_buffer* first,
 
 
 static alts_zero_copy_grpc_protector_test_fixture*
 static alts_zero_copy_grpc_protector_test_fixture*
 alts_zero_copy_grpc_protector_test_fixture_create(bool rekey,
 alts_zero_copy_grpc_protector_test_fixture_create(bool rekey,
-                                                  bool integrity_only) {
+                                                  bool integrity_only,
+                                                  bool enable_extra_copy) {
   alts_zero_copy_grpc_protector_test_fixture* fixture =
   alts_zero_copy_grpc_protector_test_fixture* fixture =
       static_cast<alts_zero_copy_grpc_protector_test_fixture*>(
       static_cast<alts_zero_copy_grpc_protector_test_fixture*>(
           gpr_zalloc(sizeof(alts_zero_copy_grpc_protector_test_fixture)));
           gpr_zalloc(sizeof(alts_zero_copy_grpc_protector_test_fixture)));
@@ -111,10 +112,12 @@ alts_zero_copy_grpc_protector_test_fixture_create(bool rekey,
   gsec_test_random_array(&key, key_length);
   gsec_test_random_array(&key, key_length);
   GPR_ASSERT(alts_zero_copy_grpc_protector_create(
   GPR_ASSERT(alts_zero_copy_grpc_protector_create(
                  key, key_length, rekey, /*is_client=*/true, integrity_only,
                  key, key_length, rekey, /*is_client=*/true, integrity_only,
-                 &max_protected_frame_size, &fixture->client) == TSI_OK);
+                 enable_extra_copy, &max_protected_frame_size,
+                 &fixture->client) == TSI_OK);
   GPR_ASSERT(alts_zero_copy_grpc_protector_create(
   GPR_ASSERT(alts_zero_copy_grpc_protector_create(
                  key, key_length, rekey, /*is_client=*/false, integrity_only,
                  key, key_length, rekey, /*is_client=*/false, integrity_only,
-                 &max_protected_frame_size, &fixture->server) == TSI_OK);
+                 enable_extra_copy, &max_protected_frame_size,
+                 &fixture->server) == TSI_OK);
   gpr_free(key);
   gpr_free(key);
   grpc_core::ExecCtx::Get()->Flush();
   grpc_core::ExecCtx::Get()->Flush();
   return fixture;
   return fixture;
@@ -229,62 +232,70 @@ static void seal_unseal_large_buffer(tsi_zero_copy_grpc_protector* sender,
 
 
 /* --- Test cases. --- */
 /* --- Test cases. --- */
 
 
-static void alts_zero_copy_protector_seal_unseal_small_buffer_tests() {
+static void alts_zero_copy_protector_seal_unseal_small_buffer_tests(
+    bool enable_extra_copy) {
   alts_zero_copy_grpc_protector_test_fixture* fixture =
   alts_zero_copy_grpc_protector_test_fixture* fixture =
       alts_zero_copy_grpc_protector_test_fixture_create(
       alts_zero_copy_grpc_protector_test_fixture_create(
-          /*rekey=*/false, /*integrity_only=*/true);
+          /*rekey=*/false, /*integrity_only=*/true, enable_extra_copy);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 
 
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
-      /*rekey=*/false, /*integrity_only=*/false);
+      /*rekey=*/false, /*integrity_only=*/false, enable_extra_copy);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 
 
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
-      /*rekey=*/true, /*integrity_only=*/true);
+      /*rekey=*/true, /*integrity_only=*/true, enable_extra_copy);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 
 
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
-      /*rekey=*/true, /*integrity_only=*/false);
+      /*rekey=*/true, /*integrity_only=*/false, enable_extra_copy);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->client, fixture->server);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   seal_unseal_small_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 }
 }
 
 
-static void alts_zero_copy_protector_seal_unseal_large_buffer_tests() {
+static void alts_zero_copy_protector_seal_unseal_large_buffer_tests(
+    bool enable_extra_copy) {
   alts_zero_copy_grpc_protector_test_fixture* fixture =
   alts_zero_copy_grpc_protector_test_fixture* fixture =
       alts_zero_copy_grpc_protector_test_fixture_create(
       alts_zero_copy_grpc_protector_test_fixture_create(
-          /*rekey=*/false, /*integrity_only=*/true);
+          /*rekey=*/false, /*integrity_only=*/true, enable_extra_copy);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 
 
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
-      /*rekey=*/false, /*integrity_only=*/false);
+      /*rekey=*/false, /*integrity_only=*/false, enable_extra_copy);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 
 
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
-      /*rekey=*/true, /*integrity_only=*/true);
+      /*rekey=*/true, /*integrity_only=*/true, enable_extra_copy);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 
 
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
-      /*rekey=*/true, /*integrity_only=*/false);
+      /*rekey=*/true, /*integrity_only=*/false, enable_extra_copy);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->client, fixture->server);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   seal_unseal_large_buffer(fixture->server, fixture->client);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
 }
 }
 
 
 int main(int argc, char** argv) {
 int main(int argc, char** argv) {
-  alts_zero_copy_protector_seal_unseal_small_buffer_tests();
-  alts_zero_copy_protector_seal_unseal_large_buffer_tests();
+  alts_zero_copy_protector_seal_unseal_small_buffer_tests(
+      /*enable_extra_copy=*/false);
+  alts_zero_copy_protector_seal_unseal_small_buffer_tests(
+      /*enable_extra_copy=*/true);
+  alts_zero_copy_protector_seal_unseal_large_buffer_tests(
+      /*enable_extra_copy=*/false);
+  alts_zero_copy_protector_seal_unseal_large_buffer_tests(
+      /*enable_extra_copy=*/true);
   return 0;
   return 0;
 }
 }

+ 35 - 11
test/cpp/naming/cancel_ares_query_test.cc

@@ -160,10 +160,7 @@ void CheckResolverResultAssertFailureLocked(void* arg, grpc_error* error) {
   gpr_mu_unlock(args->mu);
   gpr_mu_unlock(args->mu);
 }
 }
 
 
-TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
-  grpc_core::ExecCtx exec_ctx;
-  ArgsStruct args;
-  ArgsInit(&args);
+void TestCancelActiveDNSQuery(ArgsStruct* args) {
   int fake_dns_port = grpc_pick_unused_port_or_die();
   int fake_dns_port = grpc_pick_unused_port_or_die();
   FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port);
   FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port);
   char* client_target;
   char* client_target;
@@ -173,20 +170,47 @@ TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
       fake_dns_port));
       fake_dns_port));
   // create resolver and resolve
   // create resolver and resolve
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
-      grpc_core::ResolverRegistry::CreateResolver(client_target, nullptr,
-                                                  args.pollset_set, args.lock);
+      grpc_core::ResolverRegistry::CreateResolver(
+          client_target, nullptr, args->pollset_set, args->lock);
   gpr_free(client_target);
   gpr_free(client_target);
   grpc_closure on_resolver_result_changed;
   grpc_closure on_resolver_result_changed;
   GRPC_CLOSURE_INIT(&on_resolver_result_changed,
   GRPC_CLOSURE_INIT(&on_resolver_result_changed,
-                    CheckResolverResultAssertFailureLocked, (void*)&args,
-                    grpc_combiner_scheduler(args.lock));
-  resolver->NextLocked(&args.channel_args, &on_resolver_result_changed);
+                    CheckResolverResultAssertFailureLocked, (void*)args,
+                    grpc_combiner_scheduler(args->lock));
+  resolver->NextLocked(&args->channel_args, &on_resolver_result_changed);
   // Without resetting and causing resolver shutdown, the
   // Without resetting and causing resolver shutdown, the
   // PollPollsetUntilRequestDone call should never finish.
   // PollPollsetUntilRequestDone call should never finish.
   resolver.reset();
   resolver.reset();
   grpc_core::ExecCtx::Get()->Flush();
   grpc_core::ExecCtx::Get()->Flush();
-  PollPollsetUntilRequestDone(&args);
-  ArgsFinish(&args);
+  PollPollsetUntilRequestDone(args);
+  ArgsFinish(args);
+}
+
+TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
+  grpc_core::ExecCtx exec_ctx;
+  ArgsStruct args;
+  ArgsInit(&args);
+  TestCancelActiveDNSQuery(&args);
+}
+
+TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
+  grpc_core::ExecCtx exec_ctx;
+  ArgsStruct args;
+  ArgsInit(&args);
+  // Add fake_other_pollset_set into the mix to test
+  // that we're explicitly deleting fd's from their pollset.
+  // If we aren't doing so, then the remaining presence of
+  // "fake_other_pollset_set" after the request is done and the resolver
+  // pollset set is destroyed should keep the resolver's fd alive and
+  // fail the test.
+  grpc_pollset_set* fake_other_pollset_set = grpc_pollset_set_create();
+  grpc_pollset_set_add_pollset_set(fake_other_pollset_set, args.pollset_set);
+  // Note that running the cancellation c-ares test is somewhat irrelevant for
+  // this test. This test only cares about what happens to fd's that c-ares
+  // opens.
+  TestCancelActiveDNSQuery(&args);
+  EXPECT_EQ(grpc_iomgr_count_objects_for_testing(), 0u);
+  grpc_pollset_set_destroy(fake_other_pollset_set);
 }
 }
 
 
 TEST(CancelDuringAresQuery,
 TEST(CancelDuringAresQuery,

+ 1 - 0
third_party/libcxx

@@ -0,0 +1 @@
+Subproject commit 6599cac0965be8e5a835ab7a5684bbef033d5ad0

+ 1 - 0
third_party/libcxxabi

@@ -0,0 +1 @@
+Subproject commit 9245d481eb3e890f708ff2d7dadf2a10c04748ba

+ 1 - 0
tools/doxygen/Doxyfile.c++

@@ -900,6 +900,7 @@ include/grpc/impl/codegen/sync_custom.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
 include/grpc/slice.h \
 include/grpc/slice.h \
 include/grpc/slice_buffer.h \
 include/grpc/slice_buffer.h \
 include/grpc/status.h \
 include/grpc/status.h \

+ 2 - 0
tools/doxygen/Doxyfile.c++.internal

@@ -901,6 +901,7 @@ include/grpc/impl/codegen/sync_custom.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
 include/grpc/slice.h \
 include/grpc/slice.h \
 include/grpc/slice_buffer.h \
 include/grpc/slice_buffer.h \
 include/grpc/status.h \
 include/grpc/status.h \
@@ -1028,6 +1029,7 @@ src/core/lib/compression/stream_compression_identity.h \
 src/core/lib/debug/stats.h \
 src/core/lib/debug/stats.h \
 src/core/lib/debug/stats_data.h \
 src/core/lib/debug/stats_data.h \
 src/core/lib/debug/trace.h \
 src/core/lib/debug/trace.h \
+src/core/lib/gpr/alloc.h \
 src/core/lib/gpr/arena.h \
 src/core/lib/gpr/arena.h \
 src/core/lib/gpr/env.h \
 src/core/lib/gpr/env.h \
 src/core/lib/gpr/host_port.h \
 src/core/lib/gpr/host_port.h \

+ 1 - 0
tools/doxygen/Doxyfile.core

@@ -840,6 +840,7 @@ include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
 include/grpc/slice.h \
 include/grpc/slice.h \
 include/grpc/slice_buffer.h \
 include/grpc/slice_buffer.h \
 include/grpc/status.h \
 include/grpc/status.h \

+ 4 - 0
tools/doxygen/Doxyfile.core.internal

@@ -840,6 +840,7 @@ include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
 include/grpc/slice.h \
 include/grpc/slice.h \
 include/grpc/slice_buffer.h \
 include/grpc/slice_buffer.h \
 include/grpc/status.h \
 include/grpc/status.h \
@@ -891,7 +892,9 @@ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
 src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
 src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c \
+src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c \
+src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \
 src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
 src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
@@ -1070,6 +1073,7 @@ src/core/lib/debug/trace.cc \
 src/core/lib/debug/trace.h \
 src/core/lib/debug/trace.h \
 src/core/lib/gpr/README.md \
 src/core/lib/gpr/README.md \
 src/core/lib/gpr/alloc.cc \
 src/core/lib/gpr/alloc.cc \
+src/core/lib/gpr/alloc.h \
 src/core/lib/gpr/arena.cc \
 src/core/lib/gpr/arena.cc \
 src/core/lib/gpr/arena.h \
 src/core/lib/gpr/arena.h \
 src/core/lib/gpr/atm.cc \
 src/core/lib/gpr/atm.cc \

+ 1 - 1
tools/internal_ci/linux/grpc_asan_on_foundry.sh

@@ -14,6 +14,6 @@
 # limitations under the License.
 # limitations under the License.
 
 
 export UPLOAD_TEST_RESULTS=true
 export UPLOAD_TEST_RESULTS=true
-EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=address --linkopt=-fsanitize=address --test_timeout=3600"
+EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=address --linkopt=-fsanitize=address --test_timeout=3600 --runs_per_test_detects_flakes --runs_per_test=2"
 github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
 github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
 
 

+ 2 - 0
tools/internal_ci/linux/grpc_ubsan_on_foundry.sh

@@ -60,6 +60,8 @@ source tools/internal_ci/helper_scripts/prepare_build_linux_rc
   --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 \
   --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 \
   --extra_toolchains=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.13.0/cpp:cc-toolchain-clang-x86_64-default \
   --extra_toolchains=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.13.0/cpp:cc-toolchain-clang-x86_64-default \
   --extra_execution_platforms=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0:rbe_ubuntu1604 \
   --extra_execution_platforms=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0:rbe_ubuntu1604 \
+  --runs_per_test_detects_flakes \
+  --runs_per_test=2 \
   -- //test/... || FAILED="true"
   -- //test/... || FAILED="true"
 
 
 # Sleep to let ResultStore finish writing results before querying
 # Sleep to let ResultStore finish writing results before querying

+ 19 - 0
tools/internal_ci/linux/pull_request/grpc_asan_on_foundry.sh

@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Copyright 2017 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.
+
+export UPLOAD_TEST_RESULTS=true
+EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=address --linkopt=-fsanitize=address --test_timeout=3600"
+github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
+

+ 68 - 0
tools/internal_ci/linux/pull_request/grpc_ubsan_on_foundry.sh

@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+# Copyright 2017 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.
+
+set -ex
+
+# A temporary solution to give Kokoro credentials. 
+# The file name 4321_grpc-testing-service needs to match auth_credential in 
+# the build config.
+# TODO: Use keystore.
+mkdir -p ${KOKORO_KEYSTORE_DIR}
+cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321_grpc-testing-service
+
+temp_dir=$(mktemp -d)
+ln -f "${KOKORO_GFILE_DIR}/bazel-rc-0.14.0rc5" ${temp_dir}/bazel
+chmod 755 "${KOKORO_GFILE_DIR}/bazel-rc-0.14.0rc5"
+export PATH="${temp_dir}:${PATH}"
+# This should show ${temp_dir}/bazel
+which bazel
+chmod +x "${KOKORO_GFILE_DIR}/bazel_wrapper.py"
+
+# change to grpc repo root
+cd $(dirname $0)/../../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+"${KOKORO_GFILE_DIR}/bazel_wrapper.py" \
+  --host_jvm_args=-Dbazel.DigestFunction=SHA256 \
+  test --jobs="200" \
+  --test_timeout="3600,3600,3600,3600" \
+  --test_output=errors  \
+  --verbose_failures=true  \
+  --keep_going  \
+  --remote_accept_cached=true  \
+  --spawn_strategy=remote  \
+  --remote_local_fallback=false  \
+  --remote_timeout=3600  \
+  --strategy=Javac=remote  \
+  --strategy=Closure=remote  \
+  --genrule_strategy=remote  \
+  --experimental_strict_action_env=true \
+  --experimental_remote_platform_override='properties:{name:"container-image" value:"docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:59bf0e191a6b5cc1ab62c2224c810681d1326bad5a27b1d36c9f40113e79da7f" }' \
+  --define GRPC_PORT_ISOLATED_RUNTIME=1 \
+  --copt=-gmlt \
+  --strip=never \
+  --copt=-fsanitize=undefined \
+  --linkopt=-fsanitize=undefined \
+  --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/ubuntu16_04_clang/1.0/bazel_0.13.0/ubsan:toolchain \
+  --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 \
+  --extra_toolchains=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.13.0/cpp:cc-toolchain-clang-x86_64-default \
+  --extra_execution_platforms=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0:rbe_ubuntu1604 \
+  -- //test/... || FAILED="true"
+
+if [ "$FAILED" != "" ]
+then
+  exit 1
+fi

+ 15 - 0
tools/interop_matrix/client_matrix.py

@@ -93,6 +93,9 @@ LANG_RELEASE_MATRIX = {
         {
         {
             'v1.12.0': None
             'v1.12.0': None
         },
         },
+        {
+            'v1.13.0': None
+        },
     ],
     ],
     'go': [
     'go': [
         {
         {
@@ -213,6 +216,9 @@ LANG_RELEASE_MATRIX = {
         {
         {
             'v1.12.0': None
             'v1.12.0': None
         },
         },
+        {
+            'v1.13.0': None
+        },
     ],
     ],
     'node': [
     'node': [
         {
         {
@@ -289,6 +295,9 @@ LANG_RELEASE_MATRIX = {
         {
         {
             'v1.12.0': None
             'v1.12.0': None
         },
         },
+        {
+            'v1.13.0': None
+        },
     ],
     ],
     'php': [
     'php': [
         {
         {
@@ -327,6 +336,9 @@ LANG_RELEASE_MATRIX = {
         {
         {
             'v1.12.0': None
             'v1.12.0': None
         },
         },
+        {
+            'v1.13.0': None
+        },
     ],
     ],
     'csharp': [
     'csharp': [
         {
         {
@@ -370,6 +382,9 @@ LANG_RELEASE_MATRIX = {
         {
         {
             'v1.12.0': None
             'v1.12.0': None
         },
         },
+        {
+            'v1.13.0': None
+        },
     ],
     ],
 }
 }
 
 

+ 39 - 0
tools/run_tests/generated/sources_and_headers.json

@@ -449,6 +449,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": "ev_epollex_linux_test", 
+    "src": [
+      "test/core/iomgr/ev_epollex_linux_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
   {
   {
     "deps": [
     "deps": [
       "gpr", 
       "gpr", 
@@ -6850,6 +6867,16 @@
     "third_party": false, 
     "third_party": false, 
     "type": "lib"
     "type": "lib"
   }, 
   }, 
+  {
+    "deps": [], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
+    "name": "cxxabi", 
+    "src": [], 
+    "third_party": false, 
+    "type": "lib"
+  }, 
   {
   {
     "deps": [
     "deps": [
       "gpr_base"
       "gpr_base"
@@ -9139,6 +9166,7 @@
       "include/grpc/support/sync_windows.h", 
       "include/grpc/support/sync_windows.h", 
       "include/grpc/support/thd_id.h", 
       "include/grpc/support/thd_id.h", 
       "include/grpc/support/time.h", 
       "include/grpc/support/time.h", 
+      "src/core/lib/gpr/alloc.h", 
       "src/core/lib/gpr/arena.h", 
       "src/core/lib/gpr/arena.h", 
       "src/core/lib/gpr/env.h", 
       "src/core/lib/gpr/env.h", 
       "src/core/lib/gpr/host_port.h", 
       "src/core/lib/gpr/host_port.h", 
@@ -9185,6 +9213,7 @@
       "include/grpc/support/sync_windows.h", 
       "include/grpc/support/sync_windows.h", 
       "include/grpc/support/thd_id.h", 
       "include/grpc/support/thd_id.h", 
       "include/grpc/support/time.h", 
       "include/grpc/support/time.h", 
+      "src/core/lib/gpr/alloc.h", 
       "src/core/lib/gpr/arena.h", 
       "src/core/lib/gpr/arena.h", 
       "src/core/lib/gpr/env.h", 
       "src/core/lib/gpr/env.h", 
       "src/core/lib/gpr/host_port.h", 
       "src/core/lib/gpr/host_port.h", 
@@ -9460,6 +9489,7 @@
       "include/grpc/grpc.h", 
       "include/grpc/grpc.h", 
       "include/grpc/grpc_posix.h", 
       "include/grpc/grpc_posix.h", 
       "include/grpc/grpc_security_constants.h", 
       "include/grpc/grpc_security_constants.h", 
+      "include/grpc/load_reporting.h", 
       "include/grpc/slice.h", 
       "include/grpc/slice.h", 
       "include/grpc/slice_buffer.h", 
       "include/grpc/slice_buffer.h", 
       "include/grpc/status.h", 
       "include/grpc/status.h", 
@@ -9609,6 +9639,7 @@
       "include/grpc/grpc.h", 
       "include/grpc/grpc.h", 
       "include/grpc/grpc_posix.h", 
       "include/grpc/grpc_posix.h", 
       "include/grpc/grpc_security_constants.h", 
       "include/grpc/grpc_security_constants.h", 
+      "include/grpc/load_reporting.h", 
       "include/grpc/slice.h", 
       "include/grpc/slice.h", 
       "include/grpc/slice_buffer.h", 
       "include/grpc/slice_buffer.h", 
       "include/grpc/status.h", 
       "include/grpc/status.h", 
@@ -9958,6 +9989,8 @@
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
     ], 
     ], 
     "is_filegroup": true, 
     "is_filegroup": true, 
@@ -9975,7 +10008,9 @@
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
     ], 
     ], 
@@ -9997,6 +10032,8 @@
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
     ], 
     ], 
     "is_filegroup": true, 
     "is_filegroup": true, 
@@ -10014,7 +10051,9 @@
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
       "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
     ], 
     ], 

+ 20 - 0
tools/run_tests/generated/tests.json

@@ -561,6 +561,26 @@
     ], 
     ], 
     "uses_polling": false
     "uses_polling": false
   }, 
   }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 3, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "ev_epollex_linux_test", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": true
+  }, 
   {
   {
     "args": [], 
     "args": [], 
     "benchmark": false, 
     "benchmark": false, 

+ 9 - 7
tools/run_tests/sanity/check_submodules.sh

@@ -26,16 +26,18 @@ want_submodules=$(mktemp /tmp/submXXXXXX)
 
 
 git submodule | awk '{ print $1 }' | sort > "$submodules"
 git submodule | awk '{ print $1 }' | sort > "$submodules"
 cat << EOF | awk '{ print $1 }' | sort > "$want_submodules"
 cat << EOF | awk '{ print $1 }' | sort > "$want_submodules"
+ cc4bed2d74f7c8717e31f9579214ab52a9c9c610 third_party/abseil-cpp (cc4bed2)
  5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8 third_party/benchmark (v1.2.0)
  5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8 third_party/benchmark (v1.2.0)
- 70ef9596bbcc11353b9bb8d4e91478694dd21439 third_party/boringssl (fips-20170615-704-g70ef9596)
- dcd3e6e6ecddf059adb48fca45bc7346a108bdd9 third_party/boringssl-with-bazel (version_for_cocoapods_10.0-369-gdcd3e6e6)
- 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0)
+ 73594cde8c9a52a102c4341c244c833aa61b9c06 third_party/bloaty (remotes/origin/wide-14-g73594cd)
+ 70ef9596bbcc11353b9bb8d4e91478694dd21439 third_party/boringssl (fips-20170615-704-g70ef959)
+ dcd3e6e6ecddf059adb48fca45bc7346a108bdd9 third_party/boringssl-with-bazel (version_for_cocoapods_10.0-369-gdcd3e6e)
+ 3be1924221e1326df520f8498d704a5c4c8d0cce third_party/cares/cares (cares-1_13_0)
+ 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0-5-g30dbc81)
  ec44c6c1675c25b9827aacd08c02433cccde7780 third_party/googletest (release-1.8.0)
  ec44c6c1675c25b9827aacd08c02433cccde7780 third_party/googletest (release-1.8.0)
- b5fbb742af122b565925987e65c08957739976a7 third_party/protobuf (v3.5.2)
+ 6599cac0965be8e5a835ab7a5684bbef033d5ad0 third_party/libcxx (heads/release_60)
+ 9245d481eb3e890f708ff2d7dadf2a10c04748ba third_party/libcxxabi (heads/release_60)
+ b5fbb742af122b565925987e65c08957739976a7 third_party/protobuf (v3.3.1-641-gb5fbb74)
  cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11)
  cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11)
- 3be1924221e1326df520f8498d704a5c4c8d0cce third_party/cares/cares (cares-1_13_0)
- 73594cde8c9a52a102c4341c244c833aa61b9c06 third_party/bloaty
- cc4bed2d74f7c8717e31f9579214ab52a9c9c610 third_party/abseil-cpp
 EOF
 EOF
 
 
 diff -u "$submodules" "$want_submodules"
 diff -u "$submodules" "$want_submodules"