Merge pull request #13957 from jtattermusch/connectivity_watcher_wo_exceptions

Do not throw and eat exceptions in C# connectivity watcher
diff --git a/BUILD b/BUILD
index dba6592..804c6ce 100644
--- a/BUILD
+++ b/BUILD
@@ -1006,7 +1006,6 @@
         "include/grpc/impl/codegen/byte_buffer_reader.h",
         "include/grpc/impl/codegen/compression_types.h",
         "include/grpc/impl/codegen/connectivity_state.h",
-        "include/grpc/impl/codegen/exec_ctx_fwd.h",
         "include/grpc/impl/codegen/grpc_types.h",
         "include/grpc/impl/codegen/propagation_bits.h",
         "include/grpc/impl/codegen/status.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eed1205..78ccfb2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -594,6 +594,7 @@
 add_dependencies(buildtests_cxx thread_manager_test)
 add_dependencies(buildtests_cxx thread_stress_test)
 add_dependencies(buildtests_cxx transport_pid_controller_test)
+add_dependencies(buildtests_cxx vector_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx writes_per_rpc_test)
 endif()
@@ -1080,7 +1081,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -1394,7 +1394,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -1680,7 +1679,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -1950,7 +1948,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -2239,7 +2236,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -2552,7 +2548,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -3038,7 +3033,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -3438,7 +3432,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -3579,7 +3572,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -3784,7 +3776,6 @@
   include/grpc/impl/codegen/byte_buffer_reader.h
   include/grpc/impl/codegen/compression_types.h
   include/grpc/impl/codegen/connectivity_state.h
-  include/grpc/impl/codegen/exec_ctx_fwd.h
   include/grpc/impl/codegen/grpc_types.h
   include/grpc/impl/codegen/propagation_bits.h
   include/grpc/impl/codegen/slice.h
@@ -12497,6 +12488,45 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+
+add_executable(vector_test
+  test/core/support/vector_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(vector_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(vector_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(writes_per_rpc_test
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index af46246..c850271 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,53 +2,89 @@
 
 We definitely welcome your patches and contributions to gRPC!
 
-If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/)
+If you are new to github, please start by reading [Pull Request
+howto](https://help.github.com/articles/about-pull-requests/)
 
 ## Legal requirements
 
 In order to protect both you and ourselves, you will need to sign the
-[Contributor License Agreement](https://identity.linuxfoundation.org/projects/cncf).
+[Contributor License
+Agreement](https://identity.linuxfoundation.org/projects/cncf).
 
 ## Running tests
 
-Use `tools/run_tests/run_tests.py` script to run the unit tests.
-See [tools/run_tests](tools/run_tests) for how to run tests for a given language.
+Use `tools/run_tests/run_tests.py` script to run the unit tests.  See
+[tools/run_tests](tools/run_tests) for how to run tests for a given language.
 
-Prerequisites for building and running tests are listed in [INSTALL.md](INSTALL.md)
-and in `src/YOUR-LANGUAGE` (e.g. `src/csharp`)
+Prerequisites for building and running tests are listed in
+[INSTALL.md](INSTALL.md) and in `src/YOUR-LANGUAGE` (e.g. `src/csharp`)
 
 ## Generated project files
 
-To ease maintenance of language- and platform- specific build systems,
-many projects files are generated using templates and should not be edited
-by hand.
-Run `tools/buildgen/generate_projects.sh` to regenerate.
-See [templates](templates) for details.
+To ease maintenance of language- and platform- specific build systems, many
+projects files are generated using templates and should not be edited by hand.
+Run `tools/buildgen/generate_projects.sh` to regenerate.  See
+[templates](templates) for details.
 
-As a rule of thumb, if you see the "sanity tests" failing you've most likely edited generated files or you didn't regenerate the projects properly (or your code formatting doesn't match our code style).
+As a rule of thumb, if you see the "sanity tests" failing you've most likely
+edited generated files or you didn't regenerate the projects properly (or your
+code formatting doesn't match our code style).
 
 ## Guidelines for Pull Requests
 How to get your contributions merged smoothly and quickly.
  
-- Create **small PRs** that are narrowly focused on **addressing a single concern**. We often times receive PRs that are trying to fix several things at a time, but only one fix is considered acceptable, nothing gets merged and both author's & review's time is wasted. Create more PRs to address different concerns and everyone will be happy.
+- Create **small PRs** that are narrowly focused on **addressing a single
+  concern**.  We often times receive PRs that are trying to fix several things
+  at a time, but only one fix is considered acceptable, nothing gets merged and
+  both author's & review's time is wasted.  Create more PRs to address different
+  concerns and everyone will be happy.
  
-- For speculative changes, consider opening an issue and discussing it first. If you are suggesting a behavioral or API change, consider starting with a [gRFC proposal](https://github.com/grpc/proposal). 
+- For speculative changes, consider opening an issue and discussing it first.
+  If you are suggesting a behavioral or API change, consider starting with a
+  [gRFC proposal](https://github.com/grpc/proposal).
  
-- Provide a good **PR description** as a record of **what** change is being made and **why** it was made. Link to a github issue if it exists.
+- Provide a good **PR description** as a record of **what** change is being made
+  and **why** it was made.  Link to a GitHub issue if it exists.
  
-- Don't fix code style and formatting unless you are already changing that line to address an issue. PRs with irrelevant changes won't be merged. If you do want to fix formatting or style, do that in a separate PR.
+- Don't fix code style and formatting unless you are already changing that line
+  to address an issue.  PRs with irrelevant changes won't be merged.  If you do
+  want to fix formatting or style, do that in a separate PR.
  
-- Unless your PR is trivial, you should expect there will be reviewer comments that you'll need to address before merging. We expect you to be reasonably responsive to those comments, otherwise the PR will be closed after 2-3 weeks of inactivity.
+- Unless your PR is trivial, you should expect there will be reviewer comments
+  that you'll need to address before merging.  We expect you to be reasonably
+  responsive to those comments, otherwise the PR will be closed after 2-3 weeks
+  of inactivity.
+
+- If you have non-trivial contributions, please consider adding an entry to [the
+  AUTHORS file](https://github.com/grpc/grpc/blob/master/AUTHORS) listing the
+  copyright holder for the contribution (yourself, if you are signing the
+  individual CLA, or your company, for corporate CLAs) in the same PR as your
+  contribution.  This needs to be done only once, for each company, or
+  individual.
  
-- Maintain **clean commit history** and use **meaningful commit messages**. PRs with messy commit history are difficult to review and won't be merged. Use `rebase -i upstream/master` to curate your commit history and/or to bring in latest changes from master (but avoid rebasing in the middle of a code review).
+- Maintain **clean commit history** and use **meaningful commit messages**.
+  PRs with messy commit history are difficult to review and won't be merged.
+  Use `rebase -i upstream/master` to curate your commit history and/or to
+  bring in latest changes from master (but avoid rebasing in the middle of
+  a code review).
  
-- Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change).
+- Keep your PR up to date with upstream/master (if there are merge conflicts,
+  we can't really merge your change).
  
-- if you are regenerating the projects using `tools/buildgen/generate_projects.sh`, make changes to generated files a separate commit with commit message `regenerate projects`. Mixing changes to generated and hand-written files make your PR difficult to review.
+- If you are regenerating the projects using
+  `tools/buildgen/generate_projects.sh`, make changes to generated files a
+  separate commit with commit message `regenerate projects`.  Mixing changes
+  to generated and hand-written files make your PR difficult to review.
  
-- **All tests need to be passing** before your change can be merged. We recommend you **run tests locally** before creating your PR to catch breakages early on (see [tools/run_tests](tools/run_tests). Ultimately, the green signal will be provided by our testing infrastructure. The reviewer will help you if there are test failures that seem not related to the change you are making.
+- **All tests need to be passing** before your change can be merged.
+  We recommend you **run tests locally** before creating your PR to catch
+  breakages early on (see [tools/run_tests](tools/run_tests).  Ultimately, the
+  green signal will be provided by our testing infrastructure.  The reviewer
+  will help you if there are test failures that seem not related to the change
+  you are making.
  
-- Exceptions to the rules can be made if there's a compelling reason for doing so.
+- Exceptions to the rules can be made if there's a compelling reason for doing
+  so.
 
 
 
diff --git a/Makefile b/Makefile
index 38b4080..f50163e 100644
--- a/Makefile
+++ b/Makefile
@@ -1180,6 +1180,7 @@
 thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test
 thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
 transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test
+vector_test: $(BINDIR)/$(CONFIG)/vector_test
 writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test
 public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
 gen_hpack_tables: $(BINDIR)/$(CONFIG)/gen_hpack_tables
@@ -1620,6 +1621,7 @@
   $(BINDIR)/$(CONFIG)/thread_manager_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
   $(BINDIR)/$(CONFIG)/transport_pid_controller_test \
+  $(BINDIR)/$(CONFIG)/vector_test \
   $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
   $(BINDIR)/$(CONFIG)/boringssl_aes_test \
   $(BINDIR)/$(CONFIG)/boringssl_asn1_test \
@@ -1749,6 +1751,7 @@
   $(BINDIR)/$(CONFIG)/thread_manager_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
   $(BINDIR)/$(CONFIG)/transport_pid_controller_test \
+  $(BINDIR)/$(CONFIG)/vector_test \
   $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
   $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \
   $(BINDIR)/$(CONFIG)/resolver_component_test \
@@ -2167,6 +2170,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 )
 	$(E) "[RUN]     Testing transport_pid_controller_test"
 	$(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 )
+	$(E) "[RUN]     Testing vector_test"
+	$(Q) $(BINDIR)/$(CONFIG)/vector_test || ( echo test vector_test failed ; exit 1 )
 	$(E) "[RUN]     Testing writes_per_rpc_test"
 	$(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 )
 	$(E) "[RUN]     Testing resolver_component_tests_runner_invoker_unsecure"
@@ -3226,7 +3231,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -3540,7 +3544,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -3827,7 +3830,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -4088,7 +4090,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -4354,7 +4355,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -4646,7 +4646,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -5133,7 +5132,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -5526,7 +5524,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -5644,7 +5641,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -5854,7 +5850,6 @@
     include/grpc/impl/codegen/byte_buffer_reader.h \
     include/grpc/impl/codegen/compression_types.h \
     include/grpc/impl/codegen/connectivity_state.h \
-    include/grpc/impl/codegen/exec_ctx_fwd.h \
     include/grpc/impl/codegen/grpc_types.h \
     include/grpc/impl/codegen/propagation_bits.h \
     include/grpc/impl/codegen/slice.h \
@@ -17270,6 +17265,49 @@
 endif
 
 
+VECTOR_TEST_SRC = \
+    test/core/support/vector_test.cc \
+
+VECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(VECTOR_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/vector_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/vector_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/vector_test: $(PROTOBUF_DEP) $(VECTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(VECTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/vector_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/support/vector_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_vector_test: $(VECTOR_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(VECTOR_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 WRITES_PER_RPC_TEST_SRC = \
     test/cpp/performance/writes_per_rpc_test.cc \
 
diff --git a/Rakefile b/Rakefile
index c8a8631..74c8b1f 100755
--- a/Rakefile
+++ b/Rakefile
@@ -116,7 +116,7 @@
     system "rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
   else
     Rake::Task['dlls'].execute
-    docker_for_windows "gem update --system && bundle && rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
+    docker_for_windows "gem update --system && bundle && rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
   end
 end
 
diff --git a/build.yaml b/build.yaml
index fef7d61..db2ff88 100644
--- a/build.yaml
+++ b/build.yaml
@@ -399,6 +399,7 @@
   - src/core/lib/support/debug_location.h
   - src/core/lib/support/ref_counted.h
   - src/core/lib/support/ref_counted_ptr.h
+  - src/core/lib/support/vector.h
   - src/core/lib/surface/alarm_internal.h
   - src/core/lib/surface/api_trace.h
   - src/core/lib/surface/call.h
@@ -485,7 +486,6 @@
   - include/grpc/impl/codegen/byte_buffer_reader.h
   - include/grpc/impl/codegen/compression_types.h
   - include/grpc/impl/codegen/connectivity_state.h
-  - include/grpc/impl/codegen/exec_ctx_fwd.h
   - include/grpc/impl/codegen/grpc_types.h
   - include/grpc/impl/codegen/propagation_bits.h
   - include/grpc/impl/codegen/slice.h
@@ -4798,6 +4798,20 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: vector_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/core/support/vector_test.cc
+  deps:
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses:
+  - grpc++_test
 - name: writes_per_rpc_test
   gtest: true
   cpu_cost: 0.5
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index c127660..358fad3 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -152,7 +152,6 @@
                       'include/grpc/impl/codegen/byte_buffer_reader.h',
                       'include/grpc/impl/codegen/compression_types.h',
                       'include/grpc/impl/codegen/connectivity_state.h',
-                      'include/grpc/impl/codegen/exec_ctx_fwd.h',
                       'include/grpc/impl/codegen/grpc_types.h',
                       'include/grpc/impl/codegen/propagation_bits.h',
                       'include/grpc/impl/codegen/slice.h',
@@ -423,6 +422,7 @@
                       'src/core/lib/support/debug_location.h',
                       'src/core/lib/support/ref_counted.h',
                       'src/core/lib/support/ref_counted_ptr.h',
+                      'src/core/lib/support/vector.h',
                       'src/core/lib/surface/alarm_internal.h',
                       'src/core/lib/surface/api_trace.h',
                       'src/core/lib/surface/call.h',
@@ -903,6 +903,7 @@
                               'src/core/lib/support/debug_location.h',
                               'src/core/lib/support/ref_counted.h',
                               'src/core/lib/support/ref_counted_ptr.h',
+                              'src/core/lib/support/vector.h',
                               'src/core/lib/surface/alarm_internal.h',
                               'src/core/lib/surface/api_trace.h',
                               'src/core/lib/surface/call.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index d185995..7547bc8 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -149,7 +149,6 @@
   s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h )
   s.files += %w( include/grpc/impl/codegen/compression_types.h )
   s.files += %w( include/grpc/impl/codegen/connectivity_state.h )
-  s.files += %w( include/grpc/impl/codegen/exec_ctx_fwd.h )
   s.files += %w( include/grpc/impl/codegen/grpc_types.h )
   s.files += %w( include/grpc/impl/codegen/propagation_bits.h )
   s.files += %w( include/grpc/impl/codegen/slice.h )
@@ -349,6 +348,7 @@
   s.files += %w( src/core/lib/support/debug_location.h )
   s.files += %w( src/core/lib/support/ref_counted.h )
   s.files += %w( src/core/lib/support/ref_counted_ptr.h )
+  s.files += %w( src/core/lib/support/vector.h )
   s.files += %w( src/core/lib/surface/alarm_internal.h )
   s.files += %w( src/core/lib/surface/api_trace.h )
   s.files += %w( src/core/lib/surface/call.h )
diff --git a/include/grpc/impl/codegen/exec_ctx_fwd.h b/include/grpc/impl/codegen/exec_ctx_fwd.h
deleted file mode 100644
index 005ff14..0000000
--- a/include/grpc/impl/codegen/exec_ctx_fwd.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H
-#define GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H
-
-/* forward declaration for exec_ctx.h */
-struct grpc_exec_ctx;
-typedef struct grpc_exec_ctx grpc_exec_ctx;
-
-#endif /* GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H */
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index fcbc8ac..d481a70 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -22,7 +22,6 @@
 #include <grpc/impl/codegen/port_platform.h>
 
 #include <grpc/impl/codegen/compression_types.h>
-#include <grpc/impl/codegen/exec_ctx_fwd.h>
 #include <grpc/impl/codegen/gpr_types.h>
 #include <grpc/impl/codegen/slice.h>
 #include <grpc/impl/codegen/status.h>
diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index ad026b6..a3cd1f1 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -23,7 +23,6 @@
 
 #include <stddef.h>
 
-#include <grpc/impl/codegen/exec_ctx_fwd.h>
 #include <grpc/impl/codegen/gpr_slice.h>
 
 typedef struct grpc_slice grpc_slice;
diff --git a/include/grpc/module.modulemap b/include/grpc/module.modulemap
index 67136cb..da95515 100644
--- a/include/grpc/module.modulemap
+++ b/include/grpc/module.modulemap
@@ -30,7 +30,6 @@
   header "impl/codegen/byte_buffer_reader.h"
   header "impl/codegen/compression_types.h"
   header "impl/codegen/connectivity_state.h"
-  header "impl/codegen/exec_ctx_fwd.h"
   header "impl/codegen/grpc_types.h"
   header "impl/codegen/propagation_bits.h"
   header "impl/codegen/slice.h"
diff --git a/package.xml b/package.xml
index b4d8c88..ff3d079 100644
--- a/package.xml
+++ b/package.xml
@@ -161,7 +161,6 @@
     <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer_reader.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" />
-    <file baseinstalldir="/" name="include/grpc/impl/codegen/exec_ctx_fwd.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/grpc_types.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/propagation_bits.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" />
@@ -361,6 +360,7 @@
     <file baseinstalldir="/" name="src/core/lib/support/debug_location.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/ref_counted.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/ref_counted_ptr.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/vector.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/alarm_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/call.h" role="src" />
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
index 88af760..4c58c0e 100644
--- a/src/core/lib/iomgr/closure.h
+++ b/src/core/lib/iomgr/closure.h
@@ -22,7 +22,6 @@
 #include <grpc/support/port_platform.h>
 
 #include <assert.h>
-#include <grpc/impl/codegen/exec_ctx_fwd.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <stdbool.h>
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
index 8f8d518..5c6007c 100644
--- a/src/core/lib/iomgr/exec_ctx.h
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -111,7 +111,7 @@
 
   /** Checks if there is work to be done */
   bool HasWork() {
-    return combiner_data_.active_combiner != NULL ||
+    return combiner_data_.active_combiner != nullptr ||
            !grpc_closure_list_empty(closure_list_);
   }
 
diff --git a/src/core/lib/iomgr/gethostname_sysconf.cc b/src/core/lib/iomgr/gethostname_sysconf.cc
index e099fbd..3d74e03 100644
--- a/src/core/lib/iomgr/gethostname_sysconf.cc
+++ b/src/core/lib/iomgr/gethostname_sysconf.cc
@@ -30,7 +30,7 @@
   char* hostname = (char*)gpr_malloc(host_name_max);
   if (gethostname(hostname, host_name_max) != 0) {
     gpr_free(hostname);
-    return NULL;
+    return nullptr;
   }
   return hostname;
 }
diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h
index 3f238c6..c7cde7e 100644
--- a/src/core/lib/iomgr/iomgr.h
+++ b/src/core/lib/iomgr/iomgr.h
@@ -19,7 +19,6 @@
 #ifndef GRPC_CORE_LIB_IOMGR_IOMGR_H
 #define GRPC_CORE_LIB_IOMGR_IOMGR_H
 
-#include <grpc/impl/codegen/exec_ctx_fwd.h>
 #include "src/core/lib/iomgr/port.h"
 
 /** Initializes the iomgr. */
diff --git a/src/core/lib/iomgr/wakeup_fd_nospecial.cc b/src/core/lib/iomgr/wakeup_fd_nospecial.cc
index 4c20b8c..c2b525a 100644
--- a/src/core/lib/iomgr/wakeup_fd_nospecial.cc
+++ b/src/core/lib/iomgr/wakeup_fd_nospecial.cc
@@ -31,6 +31,6 @@
 static int check_availability_invalid(void) { return 0; }
 
 const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = {
-    NULL, NULL, NULL, NULL, check_availability_invalid};
+    nullptr, nullptr, nullptr, nullptr, check_availability_invalid};
 
 #endif /* GRPC_POSIX_NO_SPECIAL_WAKEUP_FD */
diff --git a/src/core/lib/support/env_posix.cc b/src/core/lib/support/env_posix.cc
index 7bea31c..8146330 100644
--- a/src/core/lib/support/env_posix.cc
+++ b/src/core/lib/support/env_posix.cc
@@ -31,12 +31,12 @@
 
 const char* gpr_getenv_silent(const char* name, char** dst) {
   *dst = gpr_getenv(name);
-  return NULL;
+  return nullptr;
 }
 
 char* gpr_getenv(const char* name) {
   char* result = getenv(name);
-  return result == NULL ? result : gpr_strdup(result);
+  return result == nullptr ? result : gpr_strdup(result);
 }
 
 void gpr_setenv(const char* name, const char* value) {
diff --git a/src/core/lib/support/fork.cc b/src/core/lib/support/fork.cc
index d59ca55..dc291c4 100644
--- a/src/core/lib/support/fork.cc
+++ b/src/core/lib/support/fork.cc
@@ -39,7 +39,7 @@
 #else
   fork_support_enabled = 0;
   char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
-  if (env != NULL) {
+  if (env != nullptr) {
     static const char* truthy[] = {"yes",  "Yes",  "YES", "true",
                                    "True", "TRUE", "1"};
     for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
diff --git a/src/core/lib/support/log_posix.cc b/src/core/lib/support/log_posix.cc
index 9fab480..6f93cde 100644
--- a/src/core/lib/support/log_posix.cc
+++ b/src/core/lib/support/log_posix.cc
@@ -35,15 +35,15 @@
 void gpr_log(const char* file, int line, gpr_log_severity severity,
              const char* format, ...) {
   char buf[64];
-  char* allocated = NULL;
-  char* message = NULL;
+  char* allocated = nullptr;
+  char* message = nullptr;
   int ret;
   va_list args;
   va_start(args, format);
   ret = vsnprintf(buf, sizeof(buf), format, args);
   va_end(args);
   if (ret < 0) {
-    message = NULL;
+    message = nullptr;
   } else if ((size_t)ret <= sizeof(buf) - 1) {
     message = buf;
   } else {
@@ -66,7 +66,7 @@
 
   timer = (time_t)now.tv_sec;
   final_slash = strrchr(args->file, '/');
-  if (final_slash == NULL)
+  if (final_slash == nullptr)
     display_file = args->file;
   else
     display_file = final_slash + 1;
diff --git a/src/core/lib/support/time_posix.cc b/src/core/lib/support/time_posix.cc
index 47a8494..b2087c9 100644
--- a/src/core/lib/support/time_posix.cc
+++ b/src/core/lib/support/time_posix.cc
@@ -107,7 +107,7 @@
   now.clock_type = clock;
   switch (clock) {
     case GPR_CLOCK_REALTIME:
-      gettimeofday(&now_tv, NULL);
+      gettimeofday(&now_tv, nullptr);
       now.tv_sec = now_tv.tv_sec;
       now.tv_nsec = now_tv.tv_usec * 1000;
       break;
diff --git a/src/core/lib/support/vector.h b/src/core/lib/support/vector.h
index 4a7db80..2f249a5 100644
--- a/src/core/lib/support/vector.h
+++ b/src/core/lib/support/vector.h
@@ -19,13 +19,93 @@
 #ifndef GRPC_CORE_LIB_SUPPORT_VECTOR_H
 #define GRPC_CORE_LIB_SUPPORT_VECTOR_H
 
-#include "absl/container/inlined_vector.h"
+#include <cassert>
+
 #include "src/core/lib/support/memory.h"
 
 namespace grpc_core {
 
+// NOTE: We eventually want to use absl::InlinedVector here.  However,
+// there are currently build problems that prevent us from using absl.
+// In the interim, we define a custom implementation as a place-holder,
+// with the intent to eventually replace this with the absl
+// implementation.
+//
+// This place-holder implementation does not implement the full set of
+// functionality from the absl version; it has just the methods that we
+// currently happen to need in gRPC.  If additional functionality is
+// needed before this gets replaced with the absl version, it can be
+// added, with the following proviso:
+//
+// ANY METHOD ADDED HERE MUST COMPLY WITH THE INTERFACE IN THE absl
+// IMPLEMENTATION!
+//
+// TODO(ctiller, nnoble, roth): Replace this with absl::InlinedVector
+// once we integrate absl into the gRPC build system in a usable way.
 template <typename T, size_t N>
-using InlinedVector = absl::InlinedVector<T, N, Allocator<T>>;
+class InlinedVector {
+ public:
+  InlinedVector() {}
+  ~InlinedVector() {
+    for (size_t i = 0; i < size_ && i < N; ++i) {
+      T& value = *reinterpret_cast<T*>(inline_ + i);
+      value.~T();
+    }
+    if (size_ > N) {  // Avoid subtracting two signed values.
+      for (size_t i = 0; i < size_ - N; ++i) {
+        dynamic_[i].~T();
+      }
+    }
+    gpr_free(dynamic_);
+  }
+
+  // For now, we do not support copying.
+  InlinedVector(const InlinedVector&) = delete;
+  InlinedVector& operator=(const InlinedVector&) = delete;
+
+  T& operator[](size_t offset) {
+    assert(offset < size_);
+    if (offset < N) {
+      return *reinterpret_cast<T*>(inline_ + offset);
+    } else {
+      return dynamic_[offset - N];
+    }
+  }
+
+  template <typename... Args>
+  void emplace_back(Args&&... args) {
+    if (size_ < N) {
+      new (&inline_[size_]) T(std::forward<Args>(args)...);
+    } else {
+      if (size_ - N == dynamic_capacity_) {
+        size_t new_capacity =
+            dynamic_capacity_ == 0 ? 2 : dynamic_capacity_ * 2;
+        T* new_dynamic = static_cast<T*>(gpr_malloc(sizeof(T) * new_capacity));
+        for (size_t i = 0; i < dynamic_capacity_; ++i) {
+          new (&new_dynamic[i]) T(std::move(dynamic_[i]));
+          dynamic_[i].~T();
+        }
+        gpr_free(dynamic_);
+        dynamic_ = new_dynamic;
+        dynamic_capacity_ = new_capacity;
+      }
+      new (&dynamic_[size_ - N]) T(std::forward<Args>(args)...);
+    }
+    ++size_;
+  }
+
+  void push_back(const T& value) { emplace_back(value); }
+
+  void push_back(T&& value) { emplace_back(std::move(value)); }
+
+  size_t size() const { return size_; }
+
+ private:
+  typename std::aligned_storage<sizeof(T)>::type inline_[N];
+  T* dynamic_ = nullptr;
+  size_t size_ = 0;
+  size_t dynamic_capacity_ = 0;
+};
 
 }  // namespace grpc_core
 
diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc
index ffaf327..891576f 100644
--- a/src/core/lib/transport/error_utils.cc
+++ b/src/core/lib/transport/error_utils.cc
@@ -70,7 +70,7 @@
   }
   if (code != nullptr) *code = status;
 
-  if (error_string != NULL && status != GRPC_STATUS_OK) {
+  if (error_string != nullptr && status != GRPC_STATUS_OK) {
     *error_string = gpr_strdup(grpc_error_string(error));
   }
 
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 24be042..bfc7208 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -27,7 +27,6 @@
 _USER_AGENT = 'grpc-python/{}'.format(_grpcio_metadata.__version__)
 
 _EMPTY_FLAGS = 0
-_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
 
 _UNARY_UNARY_INITIAL_DUE = (
     cygrpc.OperationType.send_initial_metadata,
@@ -61,11 +60,7 @@
 
 
 def _deadline(timeout):
-    if timeout is None:
-        return None, _INFINITE_FUTURE
-    else:
-        deadline = time.time() + timeout
-        return deadline, cygrpc.Timespec(deadline)
+    return None if timeout is None else time.time() + timeout
 
 
 def _unknown_code_details(unknown_cygrpc_code, details):
@@ -420,15 +415,15 @@
 
 
 def _start_unary_request(request, timeout, request_serializer):
-    deadline, deadline_timespec = _deadline(timeout)
+    deadline = _deadline(timeout)
     serialized_request = _common.serialize(request, request_serializer)
     if serialized_request is None:
         state = _RPCState((), (), (), grpc.StatusCode.INTERNAL,
                           'Exception serializing request!')
         rendezvous = _Rendezvous(state, None, None, deadline)
-        return deadline, deadline_timespec, None, rendezvous
+        return deadline, None, rendezvous
     else:
-        return deadline, deadline_timespec, serialized_request, None
+        return deadline, serialized_request, None
 
 
 def _end_unary_response_blocking(state, call, with_call, deadline):
@@ -453,10 +448,10 @@
         self._response_deserializer = response_deserializer
 
     def _prepare(self, request, timeout, metadata):
-        deadline, deadline_timespec, serialized_request, rendezvous = (
-            _start_unary_request(request, timeout, self._request_serializer))
+        deadline, serialized_request, rendezvous = (_start_unary_request(
+            request, timeout, self._request_serializer))
         if serialized_request is None:
-            return None, None, None, None, rendezvous
+            return None, None, None, rendezvous
         else:
             state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None)
             operations = (
@@ -467,18 +462,17 @@
                 cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
                 cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
             )
-            return state, operations, deadline, deadline_timespec, None
+            return state, operations, deadline, None
 
     def _blocking(self, request, timeout, metadata, credentials):
-        state, operations, deadline, deadline_timespec, rendezvous = self._prepare(
+        state, operations, deadline, rendezvous = self._prepare(
             request, timeout, metadata)
         if rendezvous:
             raise rendezvous
         else:
             completion_queue = cygrpc.CompletionQueue()
             call = self._channel.create_call(None, 0, completion_queue,
-                                             self._method, None,
-                                             deadline_timespec)
+                                             self._method, None, deadline)
             if credentials is not None:
                 call.set_credentials(credentials._credentials)
             call_error = call.start_client_batch(operations, None)
@@ -498,13 +492,13 @@
         return _end_unary_response_blocking(state, call, True, deadline)
 
     def future(self, request, timeout=None, metadata=None, credentials=None):
-        state, operations, deadline, deadline_timespec, rendezvous = self._prepare(
+        state, operations, deadline, rendezvous = self._prepare(
             request, timeout, metadata)
         if rendezvous:
             return rendezvous
         else:
             call, drive_call = self._managed_call(None, 0, self._method, None,
-                                                  deadline_timespec)
+                                                  deadline)
             if credentials is not None:
                 call.set_credentials(credentials._credentials)
             event_handler = _event_handler(state, call,
@@ -530,14 +524,14 @@
         self._response_deserializer = response_deserializer
 
     def __call__(self, request, timeout=None, metadata=None, credentials=None):
-        deadline, deadline_timespec, serialized_request, rendezvous = (
-            _start_unary_request(request, timeout, self._request_serializer))
+        deadline, serialized_request, rendezvous = (_start_unary_request(
+            request, timeout, self._request_serializer))
         if serialized_request is None:
             raise rendezvous
         else:
             state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None)
             call, drive_call = self._managed_call(None, 0, self._method, None,
-                                                  deadline_timespec)
+                                                  deadline)
             if credentials is not None:
                 call.set_credentials(credentials._credentials)
             event_handler = _event_handler(state, call,
@@ -573,11 +567,11 @@
         self._response_deserializer = response_deserializer
 
     def _blocking(self, request_iterator, timeout, metadata, credentials):
-        deadline, deadline_timespec = _deadline(timeout)
+        deadline = _deadline(timeout)
         state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
         completion_queue = cygrpc.CompletionQueue()
         call = self._channel.create_call(None, 0, completion_queue,
-                                         self._method, None, deadline_timespec)
+                                         self._method, None, deadline)
         if credentials is not None:
             call.set_credentials(credentials._credentials)
         with state.condition:
@@ -624,10 +618,10 @@
                timeout=None,
                metadata=None,
                credentials=None):
-        deadline, deadline_timespec = _deadline(timeout)
+        deadline = _deadline(timeout)
         state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
         call, drive_call = self._managed_call(None, 0, self._method, None,
-                                              deadline_timespec)
+                                              deadline)
         if credentials is not None:
             call.set_credentials(credentials._credentials)
         event_handler = _event_handler(state, call, self._response_deserializer)
@@ -665,10 +659,10 @@
                  timeout=None,
                  metadata=None,
                  credentials=None):
-        deadline, deadline_timespec = _deadline(timeout)
+        deadline = _deadline(timeout)
         state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None)
         call, drive_call = self._managed_call(None, 0, self._method, None,
-                                              deadline_timespec)
+                                              deadline)
         if credentials is not None:
             call.set_credentials(credentials._credentials)
         event_handler = _event_handler(state, call, self._response_deserializer)
@@ -737,7 +731,8 @@
       flags: An integer bitfield of call flags.
       method: The RPC method.
       host: A host string for the created call.
-      deadline: A cygrpc.Timespec to be the deadline of the created call.
+      deadline: A float to be the deadline of the created call or None if the
+        call is to have an infinite deadline.
 
     Returns:
       A cygrpc.Call with which to conduct an RPC and a function to call if
@@ -827,8 +822,8 @@
     completion_queue = cygrpc.CompletionQueue()
     while True:
         channel.watch_connectivity_state(connectivity,
-                                         cygrpc.Timespec(time.time() + 0.2),
-                                         completion_queue, None)
+                                         time.time() + 0.2, completion_queue,
+                                         None)
         event = completion_queue.poll()
         with state.lock:
             if not state.callbacks_and_connectivities and not state.try_to_connect:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index 443d534..efe5f2e 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -42,7 +42,7 @@
 
   def create_call(self, Call parent, int flags,
                   CompletionQueue queue not None,
-                  method, host, Timespec deadline not None):
+                  method, host, object deadline):
     if queue.is_shutting_down:
       raise ValueError("queue must not be shutting down or shutdown")
     cdef grpc_slice method_slice = _slice_from_bytes(method)
@@ -56,14 +56,13 @@
     cdef grpc_call *parent_call = NULL
     if parent is not None:
       parent_call = parent.c_call
-    with nogil:
-      operation_call.c_call = grpc_channel_create_call(
-          self.c_channel, parent_call, flags,
-          queue.c_completion_queue, method_slice, host_slice_ptr,
-          deadline.c_time, NULL)
-      grpc_slice_unref(method_slice)
-      if host_slice_ptr:
-        grpc_slice_unref(host_slice)
+    operation_call.c_call = grpc_channel_create_call(
+        self.c_channel, parent_call, flags,
+        queue.c_completion_queue, method_slice, host_slice_ptr,
+        _timespec_from_time(deadline), NULL)
+    grpc_slice_unref(method_slice)
+    if host_slice_ptr:
+      grpc_slice_unref(host_slice)
     return operation_call
 
   def check_connectivity_state(self, bint try_to_connect):
@@ -75,13 +74,12 @@
 
   def watch_connectivity_state(
       self, grpc_connectivity_state last_observed_state,
-      Timespec deadline not None, CompletionQueue queue not None, tag):
+      object deadline, CompletionQueue queue not None, tag):
     cdef _ConnectivityTag connectivity_tag = _ConnectivityTag(tag)
     cpython.Py_INCREF(connectivity_tag)
-    with nogil:
-      grpc_channel_watch_connectivity_state(
-          self.c_channel, last_observed_state, deadline.c_time,
-          queue.c_completion_queue, <cpython.PyObject *>connectivity_tag)
+    grpc_channel_watch_connectivity_state(
+        self.c_channel, last_observed_state, _timespec_from_time(deadline),
+        queue.c_completion_queue, <cpython.PyObject *>connectivity_tag)
 
   def target(self):
     cdef char *target = NULL
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index e259789..40496d1 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -52,17 +52,18 @@
       cpython.Py_DECREF(tag)
       return tag.event(event)
 
-  def poll(self, Timespec deadline=None):
+  def poll(self, deadline=None):
     # We name this 'poll' to avoid problems with CPython's expectations for
     # 'special' methods (like next and __next__).
     cdef gpr_timespec c_increment
     cdef gpr_timespec c_timeout
     cdef gpr_timespec c_deadline
+    if deadline is None:
+      c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
+    else:
+      c_deadline = _timespec_from_time(deadline)
     with nogil:
       c_increment = gpr_time_from_millis(_INTERRUPT_CHECK_PERIOD_MS, GPR_TIMESPAN)
-      c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
-      if deadline is not None:
-        c_deadline = deadline.c_time
 
       while True:
         c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
index 7b2482d..297bbad 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
@@ -18,11 +18,6 @@
 cdef grpc_slice _slice_from_bytes(bytes value) nogil
 
 
-cdef class Timespec:
-
-  cdef gpr_timespec c_time
-
-
 cdef class CallDetails:
 
   cdef grpc_call_details c_details
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index bc2cd03..b2343b5 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -123,74 +123,6 @@
   high = GRPC_COMPRESS_LEVEL_HIGH
 
 
-cdef class Timespec:
-
-  def __cinit__(self, time):
-    if time is None:
-      with nogil:
-        self.c_time = gpr_now(GPR_CLOCK_REALTIME)
-      return
-    if isinstance(time, int):
-      time = float(time)
-    if isinstance(time, float):
-      if time == float("+inf"):
-        with nogil:
-          self.c_time = gpr_inf_future(GPR_CLOCK_REALTIME)
-      elif time == float("-inf"):
-        with nogil:
-          self.c_time = gpr_inf_past(GPR_CLOCK_REALTIME)
-      else:
-        self.c_time.seconds = time
-        self.c_time.nanoseconds = (time - float(self.c_time.seconds)) * 1e9
-        self.c_time.clock_type = GPR_CLOCK_REALTIME
-    elif isinstance(time, Timespec):
-      self.c_time = (<Timespec>time).c_time
-    else:
-      raise TypeError("expected time to be float, int, or Timespec, not {}"
-                          .format(type(time)))
-
-  @property
-  def seconds(self):
-    # TODO(atash) ensure that everywhere a Timespec is created that it's
-    # converted to GPR_CLOCK_REALTIME then and not every time someone wants to
-    # read values off in Python.
-    cdef gpr_timespec real_time
-    with nogil:
-      real_time = (
-          gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME))
-    return real_time.seconds
-
-  @property
-  def nanoseconds(self):
-    cdef gpr_timespec real_time = (
-        gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME))
-    return real_time.nanoseconds
-
-  def __float__(self):
-    cdef gpr_timespec real_time = (
-        gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME))
-    return <double>real_time.seconds + <double>real_time.nanoseconds / 1e9
-
-  def __richcmp__(Timespec self not None, Timespec other not None, int op):
-    cdef gpr_timespec self_c_time = self.c_time
-    cdef gpr_timespec other_c_time = other.c_time
-    cdef int result = gpr_time_cmp(self_c_time, other_c_time)
-    if op == 0:  # <
-      return result < 0
-    elif op == 2:  # ==
-      return result == 0
-    elif op == 4:  # >
-      return result > 0
-    elif op == 1:  # <=
-      return result <= 0
-    elif op == 3:  # !=
-      return result != 0
-    elif op == 5:  # >=
-      return result >= 0
-    else:
-      raise ValueError('__richcmp__ `op` contract violated')
-
-
 cdef class CallDetails:
 
   def __cinit__(self):
@@ -213,9 +145,7 @@
 
   @property
   def deadline(self):
-    timespec = Timespec(float("-inf"))
-    timespec.c_time = self.c_details.deadline
-    return timespec
+    return _time_from_timespec(self.c_details.deadline)
 
 
 cdef class SslPemKeyCertPair:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index c19becc..e5d28a8 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -106,7 +106,7 @@
     with nogil:
       grpc_server_start(self.c_server)
     # Ensure the core has gotten a chance to do the start-up work
-    self.backup_shutdown_queue.poll(Timespec(None))
+    self.backup_shutdown_queue.poll(deadline=time.time())
 
   def add_http2_port(self, bytes address,
                      ServerCredentials server_credentials=None):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/time.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/time.pxd.pxi
new file mode 100644
index 0000000..ce67c61
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/time.pxd.pxi
@@ -0,0 +1,19 @@
+# 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.
+
+
+cdef gpr_timespec _timespec_from_time(object time)
+
+
+cdef double _time_from_timespec(gpr_timespec timespec)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/time.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/time.pyx.pxi
new file mode 100644
index 0000000..7a66868
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/time.pyx.pxi
@@ -0,0 +1,30 @@
+# 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.
+
+
+cdef gpr_timespec _timespec_from_time(object time):
+  cdef gpr_timespec timespec
+  if time is None:
+    return gpr_inf_future(GPR_CLOCK_REALTIME)
+  else:
+    timespec.seconds = time
+    timespec.nanoseconds = (time - float(timespec.seconds)) * 1e9
+    timespec.clock_type = GPR_CLOCK_REALTIME
+    return timespec
+
+
+cdef double _time_from_timespec(gpr_timespec timespec):
+  cdef gpr_timespec real_timespec = gpr_convert_clock_type(
+      timespec, GPR_CLOCK_REALTIME)
+  return <double>real_timespec.seconds + <double>real_timespec.nanoseconds / 1e9
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pxd b/src/python/grpcio/grpc/_cython/cygrpc.pxd
index b32fa51..01e2da6 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pxd
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pxd
@@ -25,3 +25,4 @@
 include "_cygrpc/security.pxd.pxi"
 include "_cygrpc/server.pxd.pxi"
 include "_cygrpc/tag.pxd.pxi"
+include "_cygrpc/time.pxd.pxi"
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index 5106394..d8ac84a 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -32,6 +32,7 @@
 include "_cygrpc/security.pyx.pxi"
 include "_cygrpc/server.pyx.pxi"
 include "_cygrpc/tag.pyx.pxi"
+include "_cygrpc/time.pyx.pxi"
 
 #
 # initialize gRPC
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index 1cdb2d4..9402941 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -220,8 +220,7 @@
             return self._state.client is not _CANCELLED and not self._state.statused
 
     def time_remaining(self):
-        return max(
-            float(self._rpc_event.call_details.deadline) - time.time(), 0)
+        return max(self._rpc_event.call_details.deadline - time.time(), 0)
 
     def cancel(self):
         self._rpc_event.call.cancel()
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
index b81d6fb..2ca1fa8 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
@@ -20,7 +20,6 @@
 from grpc.framework.foundation import logging_pool
 from tests.unit.framework.common import test_constants
 
-_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
 _EMPTY_FLAGS = 0
 _EMPTY_METADATA = ()
 
@@ -171,9 +170,9 @@
         with client_condition:
             client_calls = []
             for index in range(test_constants.RPC_CONCURRENCY):
-                client_call = channel.create_call(
-                    None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies',
-                    None, _INFINITE_FUTURE)
+                client_call = channel.create_call(None, _EMPTY_FLAGS,
+                                                  client_completion_queue,
+                                                  b'/twinkies', None, None)
                 operations = (
                     cygrpc.SendInitialMetadataOperation(_EMPTY_METADATA,
                                                         _EMPTY_FLAGS),
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
index 4eeb34b..c22c77d 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
@@ -31,9 +31,9 @@
     for _ in range(100):
         connectivity = channel.check_connectivity_state(True)
         channel.watch_connectivity_state(connectivity,
-                                         cygrpc.Timespec(time.time() + 0.2),
-                                         completion_queue, None)
-        completion_queue.poll(deadline=cygrpc.Timespec(float('+inf')))
+                                         time.time() + 0.2, completion_queue,
+                                         None)
+        completion_queue.poll()
 
 
 def _create_loop_destroy():
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_common.py b/src/python/grpcio_tests/tests/unit/_cython/_common.py
index ffd226f..d4b01ca 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_common.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_common.py
@@ -20,7 +20,6 @@
 
 RPC_COUNT = 4000
 
-INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
 EMPTY_FLAGS = 0
 
 INVOCATION_METADATA = (
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
index 4ef4ad3..7caa98f 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
@@ -41,9 +41,9 @@
                 server_request_call_tag,
             })
 
-        client_call = self.channel.create_call(
-            None, _common.EMPTY_FLAGS, self.client_completion_queue,
-            b'/twinkies', None, _common.INFINITE_FUTURE)
+        client_call = self.channel.create_call(None, _common.EMPTY_FLAGS,
+                                               self.client_completion_queue,
+                                               b'/twinkies', None, None)
         client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
         client_complete_rpc_tag = 'client_complete_rpc_tag'
         with self.client_condition:
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
index 85395c9..8582a39 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
@@ -36,9 +36,9 @@
                 server_request_call_tag,
             })
 
-        client_call = self.channel.create_call(
-            None, _common.EMPTY_FLAGS, self.client_completion_queue,
-            b'/twinkies', None, _common.INFINITE_FUTURE)
+        client_call = self.channel.create_call(None, _common.EMPTY_FLAGS,
+                                               self.client_completion_queue,
+                                               b'/twinkies', None, None)
         client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
         client_complete_rpc_tag = 'client_complete_rpc_tag'
         with self.client_condition:
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
index 82ef25b..ecd23af 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
@@ -18,7 +18,6 @@
 
 from grpc._cython import cygrpc
 
-_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
 _EMPTY_FLAGS = 0
 _EMPTY_METADATA = ()
 
@@ -156,7 +155,7 @@
 
         client_call = channel.create_call(None, _EMPTY_FLAGS,
                                           client_completion_queue, b'/twinkies',
-                                          None, _INFINITE_FUTURE)
+                                          None, None)
         client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
         client_complete_rpc_tag = 'client_complete_rpc_tag'
         with client_condition:
diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
index 5f9b74b..561adf7 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
@@ -37,21 +37,6 @@
 
 class TypeSmokeTest(unittest.TestCase):
 
-    def testTimespec(self):
-        now = time.time()
-        now_timespec_a = cygrpc.Timespec(now)
-        now_timespec_b = cygrpc.Timespec(now)
-        self.assertAlmostEqual(now, float(now_timespec_a), places=8)
-        self.assertEqual(now_timespec_a, now_timespec_b)
-        self.assertLess(cygrpc.Timespec(now - 1), cygrpc.Timespec(now))
-        self.assertGreater(cygrpc.Timespec(now + 1), cygrpc.Timespec(now))
-        self.assertGreaterEqual(cygrpc.Timespec(now + 1), cygrpc.Timespec(now))
-        self.assertGreaterEqual(cygrpc.Timespec(now), cygrpc.Timespec(now))
-        self.assertLessEqual(cygrpc.Timespec(now - 1), cygrpc.Timespec(now))
-        self.assertLessEqual(cygrpc.Timespec(now), cygrpc.Timespec(now))
-        self.assertNotEqual(cygrpc.Timespec(now - 1), cygrpc.Timespec(now))
-        self.assertNotEqual(cygrpc.Timespec(now + 1), cygrpc.Timespec(now))
-
     def testCompletionQueueUpDown(self):
         completion_queue = cygrpc.CompletionQueue()
         del completion_queue
@@ -147,7 +132,7 @@
             try:
                 call_result = call.start_client_batch(operations, tag)
                 self.assertEqual(cygrpc.CallError.ok, call_result)
-                event = queue.poll(deadline)
+                event = queue.poll(deadline=deadline)
                 self.assertEqual(cygrpc.CompletionType.operation_complete,
                                  event.completion_type)
                 self.assertTrue(event.success)
@@ -176,8 +161,6 @@
         RESPONSE = b'his name is robert paulson'
         METHOD = b'twinkies'
 
-        cygrpc_deadline = cygrpc.Timespec(DEADLINE)
-
         server_request_tag = object()
         request_call_result = self.server.request_call(
             self.server_completion_queue, self.server_completion_queue,
@@ -188,7 +171,7 @@
         client_call_tag = object()
         client_call = self.client_channel.create_call(
             None, 0, self.client_completion_queue, METHOD, self.host_argument,
-            cygrpc_deadline)
+            DEADLINE)
         client_initial_metadata = (
             (
                 CLIENT_METADATA_ASCII_KEY,
@@ -210,9 +193,9 @@
         ], client_call_tag)
         self.assertEqual(cygrpc.CallError.ok, client_start_batch_result)
         client_event_future = test_utilities.CompletionQueuePollFuture(
-            self.client_completion_queue, cygrpc_deadline)
+            self.client_completion_queue, DEADLINE)
 
-        request_event = self.server_completion_queue.poll(cygrpc_deadline)
+        request_event = self.server_completion_queue.poll(deadline=DEADLINE)
         self.assertEqual(cygrpc.CompletionType.operation_complete,
                          request_event.completion_type)
         self.assertIsInstance(request_event.call, cygrpc.Call)
@@ -223,7 +206,7 @@
         self.assertEqual(METHOD, request_event.call_details.method)
         self.assertEqual(self.expected_host, request_event.call_details.host)
         self.assertLess(
-            abs(DEADLINE - float(request_event.call_details.deadline)),
+            abs(DEADLINE - request_event.call_details.deadline),
             DEADLINE_TOLERANCE)
 
         server_call_tag = object()
@@ -248,7 +231,7 @@
         ], server_call_tag)
         self.assertEqual(cygrpc.CallError.ok, server_start_batch_result)
 
-        server_event = self.server_completion_queue.poll(cygrpc_deadline)
+        server_event = self.server_completion_queue.poll(deadline=DEADLINE)
         client_event = client_event_future.result()
 
         self.assertEqual(6, len(client_event.batch_operations))
@@ -310,7 +293,6 @@
         DEADLINE_TOLERANCE = 0.25
         METHOD = b'twinkies'
 
-        cygrpc_deadline = cygrpc.Timespec(DEADLINE)
         empty_metadata = ()
 
         server_request_tag = object()
@@ -319,26 +301,26 @@
                                  server_request_tag)
         client_call = self.client_channel.create_call(
             None, 0, self.client_completion_queue, METHOD, self.host_argument,
-            cygrpc_deadline)
+            DEADLINE)
 
         # Prologue
         def perform_client_operations(operations, description):
             return self._perform_operations(operations, client_call,
                                             self.client_completion_queue,
-                                            cygrpc_deadline, description)
+                                            DEADLINE, description)
 
         client_event_future = perform_client_operations([
             cygrpc.SendInitialMetadataOperation(empty_metadata, _EMPTY_FLAGS),
             cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
         ], "Client prologue")
 
-        request_event = self.server_completion_queue.poll(cygrpc_deadline)
+        request_event = self.server_completion_queue.poll(deadline=DEADLINE)
         server_call = request_event.call
 
         def perform_server_operations(operations, description):
             return self._perform_operations(operations, server_call,
                                             self.server_completion_queue,
-                                            cygrpc_deadline, description)
+                                            DEADLINE, description)
 
         server_event_future = perform_server_operations([
             cygrpc.SendInitialMetadataOperation(empty_metadata, _EMPTY_FLAGS),
diff --git a/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py b/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py
index 8e91161..4a00b9e 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py
@@ -49,4 +49,4 @@
 
     def __init__(self, completion_queue, deadline):
         super(CompletionQueuePollFuture,
-              self).__init__(lambda: completion_queue.poll(deadline))
+              self).__init__(lambda: completion_queue.poll(deadline=deadline))
diff --git a/test/core/iomgr/fd_conservation_posix_test.cc b/test/core/iomgr/fd_conservation_posix_test.cc
index aaa1401..4866e35 100644
--- a/test/core/iomgr/fd_conservation_posix_test.cc
+++ b/test/core/iomgr/fd_conservation_posix_test.cc
@@ -43,7 +43,7 @@
         grpc_resource_quota_create("fd_conservation_posix_test");
 
     for (i = 0; i < 100; i++) {
-      p = grpc_iomgr_create_endpoint_pair("test", NULL);
+      p = grpc_iomgr_create_endpoint_pair("test", nullptr);
       grpc_endpoint_destroy(p.client);
       grpc_endpoint_destroy(p.server);
       grpc_core::ExecCtx::Get()->Flush();
diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc
index ae26f72..07682d2 100644
--- a/test/core/iomgr/resource_quota_test.cc
+++ b/test/core/iomgr/resource_quota_test.cc
@@ -118,7 +118,7 @@
   grpc_resource_user* usr = grpc_resource_user_create(q, "usr");
   {
     grpc_core::ExecCtx exec_ctx;
-    grpc_resource_user_alloc(usr, 1024, NULL);
+    grpc_resource_user_alloc(usr, 1024, nullptr);
   }
   {
     grpc_core::ExecCtx exec_ctx;
@@ -136,7 +136,7 @@
   grpc_resource_user* usr = grpc_resource_user_create(q, "usr");
   {
     grpc_core::ExecCtx exec_ctx;
-    grpc_resource_user_alloc(usr, 1024, NULL);
+    grpc_resource_user_alloc(usr, 1024, nullptr);
     grpc_resource_user_free(usr, 1024);
   }
   grpc_resource_quota_unref(q);
@@ -565,7 +565,7 @@
   grpc_resource_user* usr = grpc_resource_user_create(q, "usr");
   {
     grpc_core::ExecCtx exec_ctx;
-    grpc_resource_user_alloc(usr, 1024, NULL);
+    grpc_resource_user_alloc(usr, 1024, nullptr);
   }
   {
     grpc_core::ExecCtx exec_ctx;
@@ -608,8 +608,8 @@
       grpc_core::ExecCtx exec_ctx;
       grpc_resource_user_alloc(usr, 1024, set_event(&allocated));
       grpc_core::ExecCtx::Get()->Flush();
-      GPR_ASSERT(gpr_event_wait(&allocated,
-                                grpc_timeout_seconds_to_deadline(5)) != NULL);
+      GPR_ASSERT(gpr_event_wait(&allocated, grpc_timeout_seconds_to_deadline(
+                                                5)) != nullptr);
       GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled,
                                 grpc_timeout_milliseconds_to_deadline(100)) ==
                  nullptr);
@@ -667,8 +667,8 @@
       grpc_core::ExecCtx exec_ctx;
       grpc_resource_user_alloc(usr, 1024, set_event(&allocated));
       grpc_core::ExecCtx::Get()->Flush();
-      GPR_ASSERT(gpr_event_wait(&allocated,
-                                grpc_timeout_seconds_to_deadline(5)) != NULL);
+      GPR_ASSERT(gpr_event_wait(&allocated, grpc_timeout_seconds_to_deadline(
+                                                5)) != nullptr);
       GPR_ASSERT(gpr_event_wait(&reclaimer_done,
                                 grpc_timeout_seconds_to_deadline(5)) !=
                  nullptr);
diff --git a/test/core/support/vector_test.cc b/test/core/support/vector_test.cc
index aad9f3b..82607a1 100644
--- a/test/core/support/vector_test.cc
+++ b/test/core/support/vector_test.cc
@@ -18,18 +18,50 @@
 
 #include "src/core/lib/support/vector.h"
 #include <gtest/gtest.h>
+#include "src/core/lib/support/memory.h"
 #include "test/core/util/test_config.h"
 
 namespace grpc_core {
 namespace testing {
 
 TEST(InlinedVectorTest, CreateAndIterate) {
-  InlinedVector<int, 1> v{1, 2, 3};
-  int sum = 0;
-  for (auto i : v) {
-    sum += i;
+  const int kNumElements = 9;
+  InlinedVector<int, 2> v;
+  for (int i = 0; i < kNumElements; ++i) {
+    v.push_back(i);
   }
-  EXPECT_EQ(6, sum);
+  EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
+  for (int i = 0; i < kNumElements; ++i) {
+    EXPECT_EQ(i, v[i]);
+  }
+}
+
+TEST(InlinedVectorTest, ValuesAreInlined) {
+  const int kNumElements = 5;
+  InlinedVector<int, 10> v;
+  for (int i = 0; i < kNumElements; ++i) {
+    v.push_back(i);
+  }
+  EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
+  for (int i = 0; i < kNumElements; ++i) {
+    EXPECT_EQ(i, v[i]);
+  }
+}
+
+TEST(InlinedVectorTest, PushBackWithMove) {
+  InlinedVector<UniquePtr<int>, 1> v;
+  UniquePtr<int> i = MakeUnique<int>(3);
+  v.push_back(std::move(i));
+  EXPECT_EQ(nullptr, i.get());
+  EXPECT_EQ(1UL, v.size());
+  EXPECT_EQ(3, *v[0]);
+}
+
+TEST(InlinedVectorTest, EmplaceBack) {
+  InlinedVector<UniquePtr<int>, 1> v;
+  v.emplace_back(New<int>(3));
+  EXPECT_EQ(1UL, v.size());
+  EXPECT_EQ(3, *v[0]);
 }
 
 }  // namespace testing
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 8d2384b..7fd36a2 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -29,7 +29,6 @@
 #include <grpc/impl/codegen/byte_buffer_reader.h>
 #include <grpc/impl/codegen/compression_types.h>
 #include <grpc/impl/codegen/connectivity_state.h>
-#include <grpc/impl/codegen/exec_ctx_fwd.h>
 #include <grpc/impl/codegen/fork.h>
 #include <grpc/impl/codegen/gpr_slice.h>
 #include <grpc/impl/codegen/gpr_types.h>
diff --git a/third_party/rake-compiler-dock/Dockerfile b/third_party/rake-compiler-dock/Dockerfile
index b4a5158..06c721c 100644
--- a/third_party/rake-compiler-dock/Dockerfile
+++ b/third_party/rake-compiler-dock/Dockerfile
@@ -1,182 +1,4 @@
-FROM ubuntu:17.04
-
-RUN apt-get -y update && \
-    apt-get install -y curl git-core xz-utils build-essential wget unzip sudo gpg dirmngr
-
-# Add "rvm" as system group, to avoid conflicts with host GIDs typically starting with 1000
-RUN groupadd -r rvm && useradd -r -g rvm -G sudo -p "" --create-home rvm && \
-    echo "source /etc/profile.d/rvm.sh" >> /etc/rubybashrc
-
-USER root
-RUN apt-get -y update && \
-    apt-get install -y gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 g++-mingw-w64-x86-64 g++-mingw-w64-i686 \
-        gcc-multilib moreutils
-USER rvm
-
-# install rvm, RVM 1.26.0+ has signed releases, source rvm for usage outside of package scripts
-RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3 && \
-    (curl -L http://get.rvm.io | sudo bash -s stable) && \
-    bash -c " \
-        source /etc/rubybashrc && \
-        rvmsudo rvm cleanup all "
-
-# Regenerate the following using build.sh if the build folder changes.
-RUN echo \\
-H4sIANslcFgAA+08a3fbxo75uvwVqOxTSbFIidTDVhKnTW0n8d28ju2ku6fO5R2RQ4kVRXJnSMve\
-OPe3LzAk9fIrvk3UuylxUnk0DwADYDADzKiD1A/c5oNvCi2E7W7rgdlpdbe3Tfxumj2zpepzeGC2\
-W+1Oy7TaZvcBNpvYHbrflq0MUpkwAfCAxVHgXIQ39uPhcB3srBsGSv8ydSMu5DeiQQrudW7Wv9Xq\
-rejf6nZ7D6D1jfhZgr+4/ve5x9IgkZADD8/sMecxbO1CZZQksR2L6PwCqCjzsjerPdrbt1++PT6x\
-j97/8t/2u1fPTp6/PXq9Uv3h4Oj48O0bVXv4+tmLA1DVe3tFS0X7s6Xw14Vs/Ys0ZN9q9d/t/zsd\
-c3X9W1a3XP/rgI0fmgM/bA6YHGnaUERpzFwX9CFUNl8c7lfoz9Hb9+8q2mTs+gL0GJrJJG6OognX\
-UsnFcm89xdJ7VXoB4mzSoI2FBlWwZjAfCvqEOh4fHFU07eXb1we7mzViAZ48eQIV7owi+GfWXNeC\
-EHQJzVSKZhA5LGgKNua6E01iP+AC0dD4StNYqta0jHJakAFdlzzRFfFTjTzdL8+OX9oHbz7sNnni\
-4AoYXBAHwsmbdR2H/vzdu6Z8//eH3tRwvhGNO/Z/s2etnv+sTrtdrv91QPOhBg/hZORLwC19KNgE\
-Rix0Ay7h+PDF4ZsTwG/gRWLKhCvBTyCJsCpKRrj2cITDpTQIxWECiMMPEx663KVeAw64rwCT8O5w\
-H0zqRR33I2eMY0nsiSxQILmpn4yg4matOLCyNBLehvDKD9PzBiBpcLNjC6DhhizIWRbEZzYEsD4S\
-iJWFF3mnjM0T5JtjNw57iQj0PWBjVsyU+FfDXIgRWU6DhjU1bcMPnSB1OTzJ0Bmjp4t1F7KZXMRc\
-Xq2eMj+hWg1lA7Hvwi60HmvaWeS7Wsa3jRipsUYfhD2d1LVP6IV8r4YD6sofjf0goG+NnNv6Y+1z\
-hnPC/FANZWLoNMAZoT0/xPLZbx/rhEUmInUUYuYkfhRCyKd2VnxMRIhowpJUIme6iawBNB/CMU8g\
-jZWwMwQpygy1KmPu+N6FakBEkCEySEawgNmQzC60sgtL8ySiWOKTOLlAnwy1H5eHTZgc1x9fweYF\
-bChz4cHCbGqZPBqwgKYBNZLvw3qrrnpnYke1j2sKcy7YT0qypKDaj5kIVCuA4DjdEH49+K/Dk+OT\
-Zyfvj2sL7Z95IHk2diY4fs6ds7imxG5+RGbyUo4Q7UlEolahbpVlIhkKhRc1uu71n/n/mCXOiMtv\
-lAf48vjfsnpdk/x/r9Uu4/91wLL+6RSkm8aOsa3H7e3OV7KH++d/OttWp9T/OuB2/YdRbKi2P0Tj\
-rvyP2VqN/3rdtlWe/9YBru95GOsM8WDHmk4Uev6QNvrBvIxnDJefQ7drdreZZxi9XrvFBwxMWtTd\
-7z0++t5hZf0vxtB6y+gb3a+wB9zf//eoqvT/a4C79U9fWaJTeKYPUnWiN8hrfDmN2/2/2eq2V/L/\
-ltUt83/rgecimkDH9HbanU6n7zmdttUeWF6/3+U722aXse5Ox3L7nttvtzvwGuOtYx6DuQ2t1iP1\
-DyxUoUZoHsErJiT8JwsxkH4SYPnnoeD+/+r4EUo3Ep7h8qfaPkv4IzhmSQPaLfgbCxGD2YPWziP6\
-tw1baBEt7Tgd/M6d5BH89u7Zyd7Lj7CHMeSQq7DTQyuFCcdAFylN8lRDZqb+IOBZJqEwVU3DkB9i\
-wc/8CCO1lbFTDAkx3B9cwCiKxn44hChEfEhFqwj+P6mPe2FVDLLNsFoBhwWBoal0SZYxQXoTJOsg\
-Cw5LJS/oqkyICLH7BeSIJBSIGtgrATfiMqwmGvGA7AuMB7GzHwJTXLp0F+OLKJzwMDG0w4S4CrHJ\
-DyTNOYiYCxhF45cRo+CfAwtkBDETCUReHrlj4M2EC4E/EExcNLAw5trvEvVIeR3hRk4+HeRP3QMh\
-fV/KFLmlrtm9z6NmEw8Io3RgoJSXncSKy6D0TTMb39zJRL8icSQVRlPKUqA6VZ6IJD8TO8zFPhmL\
-QS7yhjYd+c6IBicXse8osS5OlJ8nJFrwkIuGmpqv8lFTSvfMjMaFOGCJF4mJdsYCmqOSmpOkCmHI\
-uctdkgfKc8ouchwkaBzKPFRood6mxOA9boCMMukThVzGyFcyUpg1ym4wB1XrkmXlE3zBJ8SlEaCo\
-GkVliDZ0xrMMV47I5xLtROWqtJnVL5gEsUbZjjOONv4u4AyNL4wS3phzpJw7uChNJ4mQMxQWgyGO\
-CMlw1HxlsXwQgeBuA097gPziTLF+qHJALi5YNyNPjEsDjiM0XkRVEbj6JjHE4yHowqsYmq7rGvGv\
-zKKJWuGh9FG3TI4NMYBLaHdhawn060ADU9EqzKQBZgctU3JB2R1Z26o3wDLB5QHPKvS6pi0dZW/m\
-YXBzW37UbbVbzOv3DMPrm52+2aejbq/TocndhlnD2dyK/eefQTd7/cYObGV/sOJv7IzBrCfIUZSi\
-ygbKY3kcfQLaY3E3Cxtq6dCVy6LNS0f4cTLv5UxcePIE2EDaeRdD8EAZmE22aXvorGvUjLpTNXUN\
-NH1OpHBTJK2pHwQ5O1IZnQdTrpaNIyIpIVv5aN5zBNglMbC/WsjST9Bi8oToT7XKxqeC6OfmAp1K\
-XXk3bWvOBRnc/TjYujcHOY2COswhipVhGXEqR7WHipKdcWvnTTXlS+r1+SgeuihI0nK71220+7Cl\
-/rbuqecNyjz7Ic9nxlSWk2xIqvx2NuvCkf1QjMrG2LkntlX/Gvawi54NoOjePuNiQd0btML8sBB2\
-Y0n35EYn44lHZfQGr7GPWpRDHnKh2CpEvoLmS0bmbKvqJZ0UnSuw+xR+u1Zdjbmx3Q43mltDu3vw\
-VQz5lCoflwQYxVk2XE2F1pb6ptSkk8iBri3VnPWb5rzImpp2UWFT34/kbS+TywVpFzSLfrfSJXXM\
-x5IOcOfkM2WRUZHvxOWCy0uNRCMhM5XFqKscF6q4hduZDJ/TdhfFPKwlRsgmuENVp9W66uZdLqrS\
-M6YCV+vCGSAnUz0NT8PKfIHPu1IHWwxutvSrQxQ7gjO3tuokPF/IZHVBLxTnK1QpgMwhE/x1yi6o\
-XhFdYUVKdPRlWWwzeTjxFS+mGMQNXolxyeMWM4YnUDGNfgV+/DEvPNmFxWc4i/K+RjFiK7lWNchO\
-RHd7Cd2jKOnNtXG7freuQ3GnDq6OMmQ6+KHW/HttZhz1wu5q1fpmE6menppkD6enVnUJw73kszjn\
-K7Sz2gFyPob66cNafkcoZ/SRdjaFav1uTPkN0B9FpM6Tp0Y9Fhh01KDI3CkzPK1J4dAe45+f1mfI\
-4zSRmZSWVEyKneIZaLU2Wzc54dXGRKQhmjyvYZEHwRK3fBHXwhdVnLvQe7mkG53ozCWtLqR7+5+7\
-nMo1fqgQztLUF4vqXNDpd+n019npNcz7HgtIUBWHhXjGz2I/mWJEpMSA51JUW9tq4hEpCs4qFPaE\
-efSSrxYMARnFL1G4hPCYZ1Hjo+sCveR36YxSDOhWYjx+pg+i8yLM687xzSNmxUd1LqirsfTcm6JJ\
-BwyPNG9VxL8oXMEn0RmdaUKZwKOjwZ4aumhgKz0WXyHe0e2a5X5Nr/2D472jw3cn9H4RvUh2yHJ/\
-qq024kLSQbOMrtEyaAVFU2mY2v+D5Pjd+T/KpkRpoqOVynsm/nK46/5n27JW8n9m22qV+b91wFLQ\
-rIIG9R5wfqBR7+owrL2xLQ+ae8xxdkwMmnuMWayzEjTfPDoLmm9uV0FzW7lN+rNNXrPw/fSyz6bn\
-f5+byo5lc+PT68M3L35Vr48/47eVl8bXRBeEI3MCFV1XWHbzYb+8P3y1/7kIFaq6zkM2CLguR5Qp\
-qc7rXV+qBh/9BgsCSoJV8xAFW4v1k4yvq3SC3EvmlbTMdquE+iM9XEEX/TwSDodfEXnkjC21NR7R\
-hmgaOw386BfvlFQmx0/u6XOuvf/tG+2v+RTkX7j/t6xeef+zDrhR/1/n6l/Bv3D/j19K/78OKO//\
-/9pwy/q3JQYu6qriD/qBu95/W2ZnZf1vd8v33+uBL17/O/2d7XbLMQzH4z2r2y7Wf3a+m/fOznPz\
-7+r81un16ei2VRToDIfnGObYXho6dOfoTSJXvXGOh+pBbkd90rtderULMmbT8AzkhaS7P7DtouSM\
-RIQB8ZBr8B9ZFCd5InEY5SLoFyuSc/XLFc8ZEQknkiOQfjiChOFHEA0tEFEauqeLCFJEgH+G+Mdl\
-GBViZM4DDE7tgIkhtz2XbvbwP448pWFWOF1NKU/GiT/hQB/DCQwnVLAFBrt4jrOHPFGt+d/Ic9kF\
-oAkGENPn6WqGO6ZkGRQrEuQoTTDIDNU7aDz7JcwZgxvYfkL5dW7HI1csRtILKL5kJOVGHtF8mLRR\
-SWdM7P5jE8vqlzkVrHHOlObszVyFFbgE6pAIW47+oSnNhjb2G3GcrFJyZfPV4ZuDN2/pN0WzUZXN\
-GYXv/qc2/5Zwjf+3jLbR+rPP/2Z5/l8L3Kj/9e3/rU6vfXX/L/M/a4Ev3v/5gLfdHdz/WbvdG2zf\
-b//f6Xfaav9XhR7t/7Md5tadojDBytKuM6vV1FU/lwlUzjev6wC7cH7B5ePs7ZQi6LAEnj4lBl3u\
-SYN+c2o/2zt4+1zTN/KL95fPPhzYxwdv9p8fvjoAU4O8A2jg+d/XNnXt+u/8Wf7fsjC4zPI/5fvf\
-tcCN+v9T/L9lYQfl/ztl/mctUPr/0v+7TZkIP7angsUxF1+dxh3+3zTN7ZXzX3sb3UC5/tcAGz+o\
-/7MG3bxRMoM2AE3bgGMyiOyeLQrVm6YAvChw1cN2mVAiQT0m/uALejw9iM4huxbLeyGKJFKv64Gp\
-9AouQF/CIB3OXxpMp1PjbDbeiMSwmfjOmCfNHdwRNG32ZiDhk5hYqc6r6Gua+IGsapoyXlzolY1P\
-6qXHgOHyZxNe22zVPxs4s4qmqYfL2OfZ0YsPhuD00ODTpXcJ3u4/m3/Xm/DZmLBYvQhhYkhP1+hZ\
-8y6c5JQN+qV7VRGqZo2GE0SSa9njkvfEieHE9Av8hmqlFynY+BuWG1T7UaNHIFr+dLRgJEsqLTMC\
-W/kra2To02XSiC7pFRiig8+alobYIikNhjKpgWKoAQ8LtPT2hp+jKzetbUXQiVyOxDZ/Mqg6+6V5\
-LgyDM2eUPZUhHiPhq3nPpyMmqnJ1isXssiHZtBRNovV9+cYSSiihhBJKKKGEEkoooYQSSiihhBJK\
-KKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhH9H+D9i0BbqAHgAAA==\
-| base64 -d | tar xzC /tmp
-
-# Import patch files for ruby and gems
-RUN cp -r /tmp/build/patches /home/rvm/patches/
-ENV BASH_ENV /etc/rubybashrc
-
-# install rubies and fix permissions on
-RUN bash -c " \
-    export CFLAGS='-s -O3 -fno-fast-math -fPIC' && \
-    echo 'about to install patches for ruby 2.4.0 from:' && \
-    ls -r ~/patches && \
-    for v in 2.4.0 ; do \
-	rvm install \$v --patch \$(echo ~/patches/ruby-\$v/* | tr ' ' ','); \
-    done && \
-    rvm cleanup all && \
-    find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
-
-# Install rake-compiler and typical gems in all Rubies
-# do not generate documentation for gems
-RUN echo "gem: --no-ri --no-rdoc" >> ~/.gemrc && \
-    bash -c " \
-        rvm all do gem install bundler rake-compiler hoe mini_portile rubygems-tasks && \
-        rvm 2.4.0 do gem install mini_portile2 && \
-        find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
-
-RUN bash -c "gem env"
-RUN bash -c "gem list rake-compiler"
-
-# Install rake-compiler's cross rubies in global dir instead of /root
-RUN sudo mkdir -p /usr/local/rake-compiler && \
-    sudo chown rvm.rvm /usr/local/rake-compiler && \
-    ln -s /usr/local/rake-compiler ~/.rake-compiler
-
-# Patch rake-compiler to avoid build of ruby extensions
-RUN cd /usr/local/rvm/gems/ruby-2.4.0/gems/rake-compiler-0.9.5 && git apply /home/rvm/patches/rake-compiler-0.9.5/*.diff ; \
-    true
-
-RUN bash -c "rvm use 2.4.0 --default && \
-    export MAKE=\"make -j`nproc`\" CFLAGS='-s -O1 -fno-omit-frame-pointer -fno-fast-math' && \
-    rake-compiler cross-ruby VERSION=2.4.0 HOST=i686-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.4.0 HOST=x86_64-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.4.0 HOST=x86_64-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.2.2 HOST=i686-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.2.2 HOST=x86_64-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.2.2 HOST=x86_64-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.1.5 HOST=i686-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.1.5 HOST=x86_64-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.1.5 HOST=x86_64-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.0.0-p645 HOST=i686-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.0.0-p645 HOST=x86_64-w64-mingw32 && \
-    rake-compiler cross-ruby VERSION=2.0.0-p645 HOST=x86_64-linux-gnu && \
-    rm -rf ~/.rake-compiler/tmp/builds ~/.rake-compiler/sources && \
-    find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
-
-RUN bash -c "rvm use 2.4.0 --default && \
-    export MAKE=\"make -j`nproc`\" CFLAGS='-m32 -s -O1 -fno-omit-frame-pointer -fno-fast-math' LDFLAGS='-m32' && \
-    rake-compiler cross-ruby VERSION=2.4.0 HOST=i686-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.2.2 HOST=i686-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.1.5 HOST=i686-linux-gnu && \
-    rake-compiler cross-ruby VERSION=2.0.0-p645 HOST=i686-linux-gnu && \
-    rm -rf ~/.rake-compiler/tmp/builds ~/.rake-compiler/sources && \
-    find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
-
-RUN bash -c " \
-    rvm alias create 2.4 2.4.0 "
-
-USER root
-
-# Fix paths in rake-compiler/config.yml and add rvm and mingw-tools to the global bashrc
-RUN sed -i -- "s:/root/.rake-compiler:/usr/local/rake-compiler:g" /usr/local/rake-compiler/config.yml && \
-    echo "source /etc/profile.d/rvm.sh" >> /etc/bash.bashrc && \
-    echo "export PATH=\$PATH:/opt/mingw/mingw32/bin" >> /etc/bash.bashrc && \
-    echo "export PATH=\$PATH:/opt/mingw/mingw64/bin" >> /etc/bash.bashrc
-
-# Install wrappers for strip commands as a workaround for "Protocol error" in boot2docker.
-RUN cp /tmp/build/strip_wrapper /root/
-RUN sudo chmod +rx /root/strip_wrapper
-RUN mv /usr/bin/i686-w64-mingw32-strip /usr/bin/i686-w64-mingw32-strip.bin && \
-    mv /usr/bin/x86_64-w64-mingw32-strip /usr/bin/x86_64-w64-mingw32-strip.bin && \
-    ln /root/strip_wrapper /usr/bin/i686-w64-mingw32-strip && \
-    ln /root/strip_wrapper /usr/bin/x86_64-w64-mingw32-strip
+FROM larskanis/rake-compiler-dock:0.6.2
 
 RUN find / -name rbconfig.rb | while read f ; do sed -i 's/0x0501/0x0600/' $f ; done
 RUN find / -name win32.h | while read f ; do sed -i 's/gettimeofday/rb_gettimeofday/' $f ; done
@@ -184,26 +6,6 @@
 RUN find / -name libwinpthread.dll.a | xargs rm
 RUN find / -name libwinpthread-1.dll | xargs rm
 RUN find / -name *msvcrt-ruby*.dll.a | while read f ; do n=`echo $f | sed s/.dll//` ; mv $f $n ; done
-RUN find /usr/local/rake-compiler/ruby -name libruby.so | xargs rm
-RUN find /usr/local/rake-compiler/ruby -name libruby-static.a | while read f ; do ar t $f | xargs ar d $f ; done
-RUN find /usr/local/rake-compiler/ruby -name libruby-static.a | while read f ; do mv $f `echo $f | sed s/-static//` ; done
-
-# Install SIGINT forwarder
-RUN cp /tmp/build/sigfw.c /root/
-RUN gcc $HOME/sigfw.c -o /usr/local/bin/sigfw
-
-# Install user mapper
-RUN cp /tmp/build/runas /usr/local/bin/
-
-# Install sudoers configuration
-RUN cp /tmp/build/sudoers /etc/sudoers.d/rake-compiler-dock
-
-# Fixup Ruby 2.4 'static' compilation issue.
-RUN echo '!<arch>' > /usr/local/rake-compiler/ruby/x86_64-linux-gnu/ruby-2.4.0/lib/libruby.a
-RUN echo '!<arch>' > /usr/local/rake-compiler/ruby/i686-linux-gnu/ruby-2.4.0/lib/libruby.a
-
-ENV RUBY_CC_VERSION 2.4.0:2.3.0:2.2.2:2.1.5:2.0.0
-
 RUN apt-get install -y g++-multilib
 
 CMD bash
diff --git a/third_party/rake-compiler-dock/build.sh b/third_party/rake-compiler-dock/build.sh
deleted file mode 100755
index ca01fa6..0000000
--- a/third_party/rake-compiler-dock/build.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-# Run this to produce the snipplet of data to insert in the Dockerfile.
-
-echo 'RUN echo \\'
-tar cz build | base64 | sed 's/$/\\/'
-echo '| base64 -d | tar xzC /tmp'
diff --git a/third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/compat-with-bundler.diff b/third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/compat-with-bundler.diff
deleted file mode 100644
index ea22bd9..0000000
--- a/third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/compat-with-bundler.diff
+++ /dev/null
@@ -1,105 +0,0 @@
-From 41f834449fc4323b2f995e8715aa5842d9fd9334 Mon Sep 17 00:00:00 2001
-From: Lars Kanis <lars@greiz-reinsdorf.de>
-Date: Sat, 30 Jan 2016 08:08:07 +0100
-Subject: [PATCH] Change the fake mechanism to be compatible with bundler.
-
-The previous fake mechanism worked by hooking onto the
-"require 'rbconfig'" call.
-This is problematic because bundler internally requires rbconfig, but doesn't
-work corretly in a faked environment.
-It then fails to load gems that are also part of the standard library, like
-json and rdoc.
-This results in issues like https://github.com/rake-compiler/rake-compiler-dock/issues/8
-
-The fake mechanism is now changed to hook onto the "require 'mkrb'" call,
-which is typically part of the extconf file, and it is where the faked platform
-values are actually needed.
-That way it is loaded after bundler/setup, so that the library paths are
-set according to the Gemfile.lock, to the native Linux libraries, before
-the fake environment is active.
-
-Please note, that the build directory of a given gem needs to be cleared,
-in order to get updated fake files. So do a "rm tmp pkg -rf".
----
- lib/rake/extensiontask.rb | 35 ++++++++++++++---------------------
- 1 file changed, 14 insertions(+), 21 deletions(-)
-
-diff --git a/lib/rake/extensiontask.rb b/lib/rake/extensiontask.rb
-index 030af96..f914919 100644
---- a/lib/rake/extensiontask.rb
-+++ b/lib/rake/extensiontask.rb
-@@ -169,8 +169,8 @@ Java extension should be preferred.
-         # now add the extconf script
-         cmd << abs_extconf.relative_path_from(abs_tmp_path)
- 
--        # rbconfig.rb will be present if we are cross compiling
--        if t.prerequisites.include?("#{tmp_path}/rbconfig.rb") then
-+        # fake.rb will be present if we are cross compiling
-+        if t.prerequisites.include?("#{tmp_path}/fake.rb") then
-           options.push(*cross_config_options(platf))
-         end
- 
-@@ -365,39 +365,30 @@ Java extension should be preferred.
-       # define compilation tasks for cross platform!
-       define_compile_tasks(for_platform, ruby_ver)
- 
--      # chain fake.rb, rbconfig.rb and mkmf.rb to Makefile generation
-+      # chain fake.rb and mkmf.rb to Makefile generation
-       file "#{tmp_path}/Makefile" => ["#{tmp_path}/fake.rb",
--                                      "#{tmp_path}/rbconfig.rb",
-                                       "#{tmp_path}/mkmf.rb"]
- 
--      # copy the file from the cross-ruby location
--      file "#{tmp_path}/rbconfig.rb" => [rbconfig_file] do |t|
-+      # copy the rbconfig from the cross-ruby location and
-+      # genearte fake.rb for different ruby versions
-+      file "#{tmp_path}/fake.rb" => [rbconfig_file] do |t|
-         File.open(t.name, 'w') do |f|
--          f.write "require 'fake.rb'\n\n"
-+          f.write fake_rb(for_platform, ruby_ver)
-           f.write File.read(t.prerequisites.first)
-         end
-       end
- 
-       # copy mkmf from cross-ruby location
-       file "#{tmp_path}/mkmf.rb" => [mkmf_file] do |t|
--        cp t.prerequisites.first, t.name
--        if ruby_ver < "1.9" && "1.9" <= RUBY_VERSION
--          File.open(t.name, 'r+t') do |f|
--            content = f.read
-+        File.open(t.name, 'w') do |f|
-+          content = File.read(t.prerequisites.first)
-+          content.sub!(/^(require ')rbconfig(')$/, '\\1fake\\2')
-+          if ruby_ver < "1.9" && "1.9" <= RUBY_VERSION
-             content.sub!(/^(      break )\*(defaults)$/, '\\1\\2.first')
-             content.sub!(/^(    return )\*(defaults)$/, '\\1\\2.first')
-             content.sub!(/^(  mfile\.)print( configuration\(srcprefix\))$/, '\\1puts\\2')
--            f.rewind
--            f.write content
--            f.truncate(f.tell)
-           end
--        end
--      end
--
--      # genearte fake.rb for different ruby versions
--      file "#{tmp_path}/fake.rb" do |t|
--        File.open(t.name, 'w') do |f|
--          f.write fake_rb(for_platform, ruby_ver)
-+          f.write content
-         end
-       end
- 
-@@ -495,8 +486,10 @@ Java extension should be preferred.
-         # "cannot load such file -- win32/resolv" when it is required later on.
-         # See also: https://github.com/tjschuck/rake-compiler-dev-box/issues/5
-         require 'resolv'
-+        require 'rbconfig'
- 
-         class Object
-+          remove_const :RbConfig
-           remove_const :RUBY_PLATFORM
-           remove_const :RUBY_VERSION
-           remove_const :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
--- 
-2.5.0.windows.1
-
diff --git a/third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/without-exts.diff b/third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/without-exts.diff
deleted file mode 100644
index 07739d3..0000000
--- a/third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/without-exts.diff
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/tasks/bin/cross-ruby.rake b/tasks/bin/cross-ruby.rake
-index 6acc816..6aa2a49 100644
---- a/tasks/bin/cross-ruby.rake
-+++ b/tasks/bin/cross-ruby.rake
-@@ -135,8 +135,7 @@ file "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile" => ["#{USER
-     "--build=#{RUBY_BUILD}",
-     '--enable-shared',
-     '--disable-install-doc',
--    '--without-tk',
--    '--without-tcl'
-+    '--with-ext='
-   ]
-
-   # Force Winsock2 for Ruby 1.8, 1.9 defaults to it
diff --git a/third_party/rake-compiler-dock/build/patches/ruby-1.8.7-p374/nop.patch b/third_party/rake-compiler-dock/build/patches/ruby-1.8.7-p374/nop.patch
deleted file mode 100644
index fac8525..0000000
--- a/third_party/rake-compiler-dock/build/patches/ruby-1.8.7-p374/nop.patch
+++ /dev/null
@@ -1,2 +0,0 @@
-diff --git a/configure b/configure
-index 55157af..6630eba 100755
diff --git a/third_party/rake-compiler-dock/build/patches/ruby-1.9.3/no_sendfile.patch b/third_party/rake-compiler-dock/build/patches/ruby-1.9.3/no_sendfile.patch
deleted file mode 100644
index d8f339e..0000000
--- a/third_party/rake-compiler-dock/build/patches/ruby-1.9.3/no_sendfile.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/configure b/configure
-index 898730c..cfe6253 100755
---- a/configure
-+++ b/configure
-@@ -14695,7 +14695,7 @@ for ac_func in fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge
- 	      setsid telldir seekdir fchmod cosh sinh tanh log2 round\
- 	      setuid setgid daemon select_large_fdset setenv unsetenv\
-               mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\
--              pread sendfile shutdown sigaltstack dl_iterate_phdr
-+              pread shutdown sigaltstack dl_iterate_phdr
- do :
-   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
- ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/third_party/rake-compiler-dock/build/patches/ruby-1.9.3/nop.patch b/third_party/rake-compiler-dock/build/patches/ruby-1.9.3/nop.patch
deleted file mode 100644
index fac8525..0000000
--- a/third_party/rake-compiler-dock/build/patches/ruby-1.9.3/nop.patch
+++ /dev/null
@@ -1,2 +0,0 @@
-diff --git a/configure b/configure
-index 55157af..6630eba 100755
diff --git a/third_party/rake-compiler-dock/build/patches/ruby-2.3.0/no_sendfile.patch b/third_party/rake-compiler-dock/build/patches/ruby-2.3.0/no_sendfile.patch
deleted file mode 100644
index 915fc7b..0000000
--- a/third_party/rake-compiler-dock/build/patches/ruby-2.3.0/no_sendfile.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/configure b/configure
-index ebe3d8c..a336b73 100755
---- a/configure
-+++ b/configure
-@@ -18943,7 +18943,6 @@ do :
-   ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile"
- if test "x$ac_cv_func_sendfile" = xyes; then :
-   cat >>confdefs.h <<_ACEOF
--#define HAVE_SENDFILE 1
- _ACEOF
- 
- fi
diff --git a/third_party/rake-compiler-dock/build/patches/ruby-2.4.0/no_sendfile.patch b/third_party/rake-compiler-dock/build/patches/ruby-2.4.0/no_sendfile.patch
deleted file mode 100644
index 915fc7b..0000000
--- a/third_party/rake-compiler-dock/build/patches/ruby-2.4.0/no_sendfile.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/configure b/configure
-index ebe3d8c..a336b73 100755
---- a/configure
-+++ b/configure
-@@ -18943,7 +18943,6 @@ do :
-   ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile"
- if test "x$ac_cv_func_sendfile" = xyes; then :
-   cat >>confdefs.h <<_ACEOF
--#define HAVE_SENDFILE 1
- _ACEOF
- 
- fi
diff --git a/third_party/rake-compiler-dock/build/runas b/third_party/rake-compiler-dock/build/runas
deleted file mode 100755
index b29ce31..0000000
--- a/third_party/rake-compiler-dock/build/runas
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-groupadd -g "$GID" "$GROUP"
-mkdir -p /tmp/home
-useradd -g "$GID" -u "$UID" -G rvm,sudo -p "" -b /tmp/home -m "$USER"
-
-HOME=$(bash <<< "echo ~$USER")
-ln -s /usr/local/rake-compiler "$HOME"/.rake-compiler
-
-sudo -u "$USER" --set-home \
-    BASH_ENV=/etc/rubybashrc \
-    -- "$@"
diff --git a/third_party/rake-compiler-dock/build/sigfw.c b/third_party/rake-compiler-dock/build/sigfw.c
deleted file mode 100644
index 291d76c..0000000
--- a/third_party/rake-compiler-dock/build/sigfw.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This program handles SIGINT and forwards it to another process.
- * It is intended to be run as PID 1.
- *
- * Docker starts processes with "docker run" as PID 1.
- * On Linux, the default signal handler for PID 1 ignores any signals.
- * Therefore Ctrl-C aka SIGINT is ignored per default.
- */
-
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-int pid = 0;
-
-void
-handle_sigint (int signum)
-{
-  if(pid)
-    kill(pid, SIGINT);
-}
-
-int main(int argc, char *argv[]){
-  struct sigaction new_action;
-  int status = -1;
-
-  /* Set up the structure to specify the new action. */
-  new_action.sa_handler = handle_sigint;
-  sigemptyset (&new_action.sa_mask);
-  new_action.sa_flags = 0;
-
-  sigaction (SIGINT, &new_action, (void*)0);
-
-  pid = fork();
-  if(pid){
-    wait(&status);
-    return WEXITSTATUS(status);
-  }else{
-    status = execvp(argv[1], &argv[1]);
-    perror("exec");
-    return status;
-  }
-}
diff --git a/third_party/rake-compiler-dock/build/strip_wrapper b/third_party/rake-compiler-dock/build/strip_wrapper
deleted file mode 100755
index 7f8a134..0000000
--- a/third_party/rake-compiler-dock/build/strip_wrapper
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env ruby
-
-# Strip file on local folder instead of a Virtualbox shared folder
-# to work around this bug: https://www.virtualbox.org/ticket/8463
-
-require 'tempfile'
-require 'fileutils'
-
-strip = "#{File.basename($0)}.bin"
-
-files = ARGV.reject{|f| f=~/^-/ }.map do |arg|
-  tmp = Tempfile.new 'strip'
-  tmp.close
-  FileUtils.cp arg, tmp.path
-  [tmp, arg]
-end
-
-options = ARGV.select{|f| f=~/^-/ } + files.map{|t,o| t.path }
-
-unless system( strip, *options )
-  exit 127
-end
-code = $?.exitstatus
-
-files.each do |tmp, orig|
-  FileUtils.rm orig
-  FileUtils.cp tmp.path, orig
-end
-
-exit code
diff --git a/third_party/rake-compiler-dock/build/sudoers b/third_party/rake-compiler-dock/build/sudoers
deleted file mode 100644
index f9f9b97..0000000
--- a/third_party/rake-compiler-dock/build/sudoers
+++ /dev/null
@@ -1 +0,0 @@
-Defaults        env_keep += "http_proxy https_proxy ftp_proxy RCD_HOST_RUBY_PLATFORM RCD_HOST_RUBY_VERSION RCD_IMAGE RUBY_CC_VERSION"
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index e62278c..5bdbcd7 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -887,7 +887,6 @@
 include/grpc/impl/codegen/byte_buffer_reader.h \
 include/grpc/impl/codegen/compression_types.h \
 include/grpc/impl/codegen/connectivity_state.h \
-include/grpc/impl/codegen/exec_ctx_fwd.h \
 include/grpc/impl/codegen/fork.h \
 include/grpc/impl/codegen/gpr_slice.h \
 include/grpc/impl/codegen/gpr_types.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index d09b325..d9184f4 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -888,7 +888,6 @@
 include/grpc/impl/codegen/byte_buffer_reader.h \
 include/grpc/impl/codegen/compression_types.h \
 include/grpc/impl/codegen/connectivity_state.h \
-include/grpc/impl/codegen/exec_ctx_fwd.h \
 include/grpc/impl/codegen/fork.h \
 include/grpc/impl/codegen/gpr_slice.h \
 include/grpc/impl/codegen/gpr_types.h \
@@ -1047,6 +1046,7 @@
 src/core/lib/support/thd_internal.h \
 src/core/lib/support/time_precise.h \
 src/core/lib/support/tmpfile.h \
+src/core/lib/support/vector.h \
 src/core/lib/surface/alarm_internal.h \
 src/core/lib/surface/api_trace.h \
 src/core/lib/surface/call.h \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index 6ce9041..916d3b1 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -818,7 +818,6 @@
 include/grpc/impl/codegen/byte_buffer_reader.h \
 include/grpc/impl/codegen/compression_types.h \
 include/grpc/impl/codegen/connectivity_state.h \
-include/grpc/impl/codegen/exec_ctx_fwd.h \
 include/grpc/impl/codegen/fork.h \
 include/grpc/impl/codegen/fork.h \
 include/grpc/impl/codegen/gpr_slice.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 1aff007..3d3c671 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -818,7 +818,6 @@
 include/grpc/impl/codegen/byte_buffer_reader.h \
 include/grpc/impl/codegen/compression_types.h \
 include/grpc/impl/codegen/connectivity_state.h \
-include/grpc/impl/codegen/exec_ctx_fwd.h \
 include/grpc/impl/codegen/fork.h \
 include/grpc/impl/codegen/fork.h \
 include/grpc/impl/codegen/gpr_slice.h \
@@ -1333,6 +1332,7 @@
 src/core/lib/support/tmpfile_msys.cc \
 src/core/lib/support/tmpfile_posix.cc \
 src/core/lib/support/tmpfile_windows.cc \
+src/core/lib/support/vector.h \
 src/core/lib/support/wrap_memcpy.cc \
 src/core/lib/surface/README.md \
 src/core/lib/surface/alarm.cc \
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index 71d3a79..5923109 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -103,6 +103,9 @@
         {
             'v1.8.2': None
         },
+        {
+            'v1.9.1': None
+        },
     ],
     'java': [
         {
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index d432bd0..51f0ac7 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -4268,6 +4268,25 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_test", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "vector_test", 
+    "src": [
+      "test/core/support/vector_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
       "grpc++_test_util", 
       "grpc_test_util"
     ], 
@@ -8250,6 +8269,7 @@
       "src/core/lib/support/debug_location.h", 
       "src/core/lib/support/ref_counted.h", 
       "src/core/lib/support/ref_counted_ptr.h", 
+      "src/core/lib/support/vector.h", 
       "src/core/lib/surface/alarm_internal.h", 
       "src/core/lib/surface/api_trace.h", 
       "src/core/lib/surface/call.h", 
@@ -8389,6 +8409,7 @@
       "src/core/lib/support/debug_location.h", 
       "src/core/lib/support/ref_counted.h", 
       "src/core/lib/support/ref_counted_ptr.h", 
+      "src/core/lib/support/vector.h", 
       "src/core/lib/surface/alarm_internal.h", 
       "src/core/lib/surface/api_trace.h", 
       "src/core/lib/surface/call.h", 
@@ -8505,7 +8526,6 @@
       "include/grpc/impl/codegen/byte_buffer_reader.h", 
       "include/grpc/impl/codegen/compression_types.h", 
       "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/exec_ctx_fwd.h", 
       "include/grpc/impl/codegen/grpc_types.h", 
       "include/grpc/impl/codegen/propagation_bits.h", 
       "include/grpc/impl/codegen/slice.h", 
@@ -8519,7 +8539,6 @@
       "include/grpc/impl/codegen/byte_buffer_reader.h", 
       "include/grpc/impl/codegen/compression_types.h", 
       "include/grpc/impl/codegen/connectivity_state.h", 
-      "include/grpc/impl/codegen/exec_ctx_fwd.h", 
       "include/grpc/impl/codegen/grpc_types.h", 
       "include/grpc/impl/codegen/propagation_bits.h", 
       "include/grpc/impl/codegen/slice.h", 
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 98517cb..6b83cec 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -4510,6 +4510,30 @@
     "ci_platforms": [
       "linux", 
       "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "vector_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
       "posix"
     ], 
     "cpu_cost": 0.5, 
diff --git a/tools/run_tests/sanity/check_sources_and_headers.py b/tools/run_tests/sanity/check_sources_and_headers.py
index 6a704eb..57ae5c5 100755
--- a/tools/run_tests/sanity/check_sources_and_headers.py
+++ b/tools/run_tests/sanity/check_sources_and_headers.py
@@ -69,13 +69,10 @@
 
 
 def target_has_header(target, name):
-    if name.startswith('absl/'): return True
-    # print target['name'], name
-    if name in target['headers']:
+    if name in target_headers_transitive[target['name']]:
         return True
-    for dep in target['deps']:
-        if target_has_header(get_target(dep), name):
-            return True
+    if name.startswith('absl/'):
+        return True
     if name in [
             'src/core/lib/profiling/stap_probes.h',
             'src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h'