Merge pull request #19435 from mhaidrygoog/grpc_to_grpc_impl

 Modify codegen to use grpc_impl namespace and other cleanup
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12998e1..a34f926 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -724,6 +724,7 @@
 add_dependencies(buildtests_cxx writes_per_rpc_test)
 endif()
 add_dependencies(buildtests_cxx xds_end2end_test)
+add_dependencies(buildtests_cxx bad_streaming_id_bad_client_test)
 add_dependencies(buildtests_cxx badreq_bad_client_test)
 add_dependencies(buildtests_cxx connection_prefix_bad_client_test)
 add_dependencies(buildtests_cxx duplicate_header_bad_client_test)
@@ -731,6 +732,7 @@
 add_dependencies(buildtests_cxx headers_bad_client_test)
 add_dependencies(buildtests_cxx initial_settings_frame_bad_client_test)
 add_dependencies(buildtests_cxx large_metadata_bad_client_test)
+add_dependencies(buildtests_cxx out_of_bounds_bad_client_test)
 add_dependencies(buildtests_cxx server_registered_method_bad_client_test)
 add_dependencies(buildtests_cxx simple_request_bad_client_test)
 add_dependencies(buildtests_cxx unknown_frame_bad_client_test)
@@ -17030,6 +17032,46 @@
 
 if (gRPC_BUILD_TESTS)
 
+add_executable(bad_streaming_id_bad_client_test
+  test/core/bad_client/tests/bad_streaming_id.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(bad_streaming_id_bad_client_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
+  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(bad_streaming_id_bad_client_test
+  ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  bad_client_test
+  grpc_test_util_unsecure
+  grpc_unsecure
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(badreq_bad_client_test
   test/core/bad_client/tests/badreq.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -17310,6 +17352,46 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(out_of_bounds_bad_client_test
+  test/core/bad_client/tests/out_of_bounds.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(out_of_bounds_bad_client_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
+  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(out_of_bounds_bad_client_test
+  ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  bad_client_test
+  grpc_test_util_unsecure
+  grpc_unsecure
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(server_registered_method_bad_client_test
   test/core/bad_client/tests/server_registered_method.cc
   third_party/googletest/googletest/src/gtest-all.cc
diff --git a/Makefile b/Makefile
index f2ef973..9930fc3 100644
--- a/Makefile
+++ b/Makefile
@@ -1291,6 +1291,7 @@
 gen_percent_encoding_tables: $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables
 boringssl_ssl_test: $(BINDIR)/$(CONFIG)/boringssl_ssl_test
 boringssl_crypto_test: $(BINDIR)/$(CONFIG)/boringssl_crypto_test
+bad_streaming_id_bad_client_test: $(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test
 badreq_bad_client_test: $(BINDIR)/$(CONFIG)/badreq_bad_client_test
 connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test
 duplicate_header_bad_client_test: $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test
@@ -1298,6 +1299,7 @@
 headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
 initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
 large_metadata_bad_client_test: $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test
+out_of_bounds_bad_client_test: $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test
 server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
 simple_request_bad_client_test: $(BINDIR)/$(CONFIG)/simple_request_bad_client_test
 unknown_frame_bad_client_test: $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test
@@ -1751,6 +1753,7 @@
   $(BINDIR)/$(CONFIG)/xds_end2end_test \
   $(BINDIR)/$(CONFIG)/boringssl_ssl_test \
   $(BINDIR)/$(CONFIG)/boringssl_crypto_test \
+  $(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test \
   $(BINDIR)/$(CONFIG)/badreq_bad_client_test \
   $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
   $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test \
@@ -1758,6 +1761,7 @@
   $(BINDIR)/$(CONFIG)/headers_bad_client_test \
   $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
   $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \
+  $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test \
   $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
   $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \
   $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \
@@ -1910,6 +1914,7 @@
   $(BINDIR)/$(CONFIG)/transport_security_common_api_test \
   $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
   $(BINDIR)/$(CONFIG)/xds_end2end_test \
+  $(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test \
   $(BINDIR)/$(CONFIG)/badreq_bad_client_test \
   $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
   $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test \
@@ -1917,6 +1922,7 @@
   $(BINDIR)/$(CONFIG)/headers_bad_client_test \
   $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
   $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \
+  $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test \
   $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
   $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \
   $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \
@@ -2441,6 +2447,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 )
 	$(E) "[RUN]     Testing xds_end2end_test"
 	$(Q) $(BINDIR)/$(CONFIG)/xds_end2end_test || ( echo test xds_end2end_test failed ; exit 1 )
+	$(E) "[RUN]     Testing bad_streaming_id_bad_client_test"
+	$(Q) $(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test || ( echo test bad_streaming_id_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing badreq_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing connection_prefix_bad_client_test"
@@ -2455,6 +2463,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing large_metadata_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test || ( echo test large_metadata_bad_client_test failed ; exit 1 )
+	$(E) "[RUN]     Testing out_of_bounds_bad_client_test"
+	$(Q) $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test || ( echo test out_of_bounds_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_registered_method_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing simple_request_bad_client_test"
@@ -20323,6 +20333,37 @@
 endif
 
 
+BAD_STREAMING_ID_BAD_CLIENT_TEST_SRC = \
+    test/core/bad_client/tests/bad_streaming_id.cc \
+
+BAD_STREAMING_ID_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_STREAMING_ID_BAD_CLIENT_TEST_SRC))))
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test: $(PROTOBUF_DEP) $(BAD_STREAMING_ID_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BAD_STREAMING_ID_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/bad_streaming_id.o:  $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bad_streaming_id_bad_client_test: $(BAD_STREAMING_ID_BAD_CLIENT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(BAD_STREAMING_ID_BAD_CLIENT_TEST_OBJS:.o=.dep)
+endif
+
+
 BADREQ_BAD_CLIENT_TEST_SRC = \
     test/core/bad_client/tests/badreq.cc \
 
@@ -20540,6 +20581,37 @@
 endif
 
 
+OUT_OF_BOUNDS_BAD_CLIENT_TEST_SRC = \
+    test/core/bad_client/tests/out_of_bounds.cc \
+
+OUT_OF_BOUNDS_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(OUT_OF_BOUNDS_BAD_CLIENT_TEST_SRC))))
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test: $(PROTOBUF_DEP) $(OUT_OF_BOUNDS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(OUT_OF_BOUNDS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/out_of_bounds.o:  $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_out_of_bounds_bad_client_test: $(OUT_OF_BOUNDS_BAD_CLIENT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(OUT_OF_BOUNDS_BAD_CLIENT_TEST_OBJS:.o=.dep)
+endif
+
+
 SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \
     test/core/bad_client/tests/server_registered_method.cc \
 
diff --git a/Rakefile b/Rakefile
index d604f79..8123dc5 100755
--- a/Rakefile
+++ b/Rakefile
@@ -124,10 +124,10 @@
         "invoked on macos with ruby #{RUBY_VERSION}. The ruby macos artifact " \
         "build should be running on ruby 2.5."
     end
-    system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
+    system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
   else
     Rake::Task['dlls'].execute
-    docker_for_windows "gem update --system --no-document && bundle && rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
+    docker_for_windows "gem update --system --no-document && bundle && rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
   end
 end
 
diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl
index 151825c..be58c52 100644
--- a/bazel/grpc_deps.bzl
+++ b/bazel/grpc_deps.bzl
@@ -67,11 +67,6 @@
     )
 
     native.bind(
-        name = "gmock",
-        actual = "@com_github_google_googletest//:gmock",
-    )
-
-    native.bind(
         name = "benchmark",
         actual = "@com_github_google_benchmark//:benchmark",
     )
@@ -144,10 +139,9 @@
     if "com_github_google_googletest" not in native.existing_rules():
         http_archive(
             name = "com_github_google_googletest",
-            build_file = "@com_github_grpc_grpc//third_party:gtest.BUILD",
-            sha256 = "175a22300b3450e27e5f2e6f95cc9abca74617cbc21a1e0ed19bdfbd22ea0305",
-            strip_prefix = "googletest-ec44c6c1675c25b9827aacd08c02433cccde7780",
-            url = "https://github.com/google/googletest/archive/ec44c6c1675c25b9827aacd08c02433cccde7780.tar.gz",
+            sha256 = "d0d447b4feeedca837a0d46a289d4223089b32ac2f84545fa4982755cc8919be",
+            strip_prefix = "googletest-2fe3bd994b3189899d93f1d5a881e725e046fdc2",
+            url = "https://github.com/google/googletest/archive/2fe3bd994b3189899d93f1d5a881e725e046fdc2.tar.gz",
         )
 
     if "com_github_gflags_gflags" not in native.existing_rules():
@@ -178,19 +172,19 @@
     if "com_google_absl" not in native.existing_rules():
         http_archive(
             name = "com_google_absl",
-            sha256 = "5fe2a3a8f8378e81d4d3db6541f48030e04233ccd2d6c7e9d981ed577b314ae8",
-            strip_prefix = "abseil-cpp-308ce31528a7edfa39f5f6d36142278a0ae1bf45",
-            url = "https://github.com/abseil/abseil-cpp/archive/308ce31528a7edfa39f5f6d36142278a0ae1bf45.tar.gz",
+            sha256 = "7ddf863ddced6fa5bf7304103f9c7aa619c20a2fcf84475512c8d3834b9d14fa",
+            strip_prefix = "abseil-cpp-61c9bf3e3e1c28a4aa6d7f1be4b37fd473bb5529",
+            url = "https://github.com/abseil/abseil-cpp/archive/61c9bf3e3e1c28a4aa6d7f1be4b37fd473bb5529.tar.gz",
         )
 
     if "bazel_toolchains" not in native.existing_rules():
         http_archive(
             name = "bazel_toolchains",
-            sha256 = "88e818f9f03628eef609c8429c210ecf265ffe46c2af095f36c7ef8b1855fef5",
-            strip_prefix = "bazel-toolchains-92dd8a7a518a2fb7ba992d47c8b38299fe0be825",
+            sha256 = "d968b414b32aa99c86977e1171645d31da2b52ac88060de3ac1e49932d5dcbf1",
+            strip_prefix = "bazel-toolchains-4bd5df80d77aa7f4fb943dfdfad5c9056a62fb47",
             urls = [
-                "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/92dd8a7a518a2fb7ba992d47c8b38299fe0be825.tar.gz",
-                "https://github.com/bazelbuild/bazel-toolchains/archive/92dd8a7a518a2fb7ba992d47c8b38299fe0be825.tar.gz",
+                "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/4bd5df80d77aa7f4fb943dfdfad5c9056a62fb47.tar.gz",
+                "https://github.com/bazelbuild/bazel-toolchains/archive/4bd5df80d77aa7f4fb943dfdfad5c9056a62fb47.tar.gz",
             ],
         )
 
@@ -205,9 +199,9 @@
     if "io_opencensus_cpp" not in native.existing_rules():
         http_archive(
             name = "io_opencensus_cpp",
-            sha256 = "3436ca23dc1b3345186defd0f46d64244079ba3d3234a0c5d6ef5e8d5d06c8b5",
-            strip_prefix = "opencensus-cpp-9b1e354e89bf3d92aedc00af45b418ce870f3d77",
-            url = "https://github.com/census-instrumentation/opencensus-cpp/archive/9b1e354e89bf3d92aedc00af45b418ce870f3d77.tar.gz",
+            sha256 = "90d6fafa8b1a2ea613bf662731d3086e1c2ed286f458a95c81744df2dbae41b1",
+            strip_prefix = "opencensus-cpp-c9a4da319bc669a772928ffc55af4a61be1a1176",
+            url = "https://github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
         )
 
     if "upb" not in native.existing_rules():
diff --git a/examples/python/compression/BUILD.bazel b/examples/python/compression/BUILD.bazel
new file mode 100644
index 0000000..b95d7cc
--- /dev/null
+++ b/examples/python/compression/BUILD.bazel
@@ -0,0 +1,44 @@
+# Copyright 2019 The 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.
+
+py_binary(
+    name = "server",
+    srcs = ["server.py"],
+    deps = [
+        "//src/python/grpcio/grpc:grpcio",
+        "//examples:py_helloworld",
+    ],
+    srcs_version = "PY2AND3",
+)
+
+py_binary(
+    name = "client",
+    srcs = ["client.py"],
+    deps = [
+        "//src/python/grpcio/grpc:grpcio",
+        "//examples:py_helloworld",
+    ],
+    srcs_version = "PY2AND3",
+)
+
+py_test(
+    name = "test/compression_example_test",
+    srcs = ["test/compression_example_test.py"],
+    srcs_version = "PY2AND3",
+    data = [
+      ":client",
+      ":server",
+    ],
+    size = "small",
+)
diff --git a/examples/python/compression/README.md b/examples/python/compression/README.md
new file mode 100644
index 0000000..c719bba
--- /dev/null
+++ b/examples/python/compression/README.md
@@ -0,0 +1,58 @@
+## Compression with gRPC Python
+
+gRPC offers lossless compression options in order to decrease the number of bits
+transferred over the wire. Three levels of compression are available:
+
+ - `grpc.Compression.NoCompression` - No compression is applied to the payload. (default)
+ - `grpc.Compression.Deflate` - The "Deflate" algorithm is applied to the payload.
+ - `grpc.Compression.Gzip` - The Gzip algorithm is applied to the payload.
+
+The default option on both clients and servers is `grpc.Compression.NoCompression`.
+
+See [the gRPC Compression Spec](https://github.com/grpc/grpc/blob/master/doc/compression.md)
+for more information.
+
+### Client Side Compression
+
+Compression may be set at two levels on the client side.
+
+#### At the channel level
+
+```python
+with grpc.insecure_channel('foo.bar:1234', compression=grpc.Compression.Gzip) as channel:
+    use_channel(channel)
+```
+
+#### At the call level
+
+Setting the compression method at the call level will override any settings on
+the channel level.
+
+```python
+stub = helloworld_pb2_grpc.GreeterStub(channel)
+response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'),
+                         compression=grpc.Compression.Deflate)
+```
+
+
+### Server Side Compression
+
+Additionally, compression may be set at two levels on the server side.
+
+#### On the entire server
+
+```python
+server = grpc.server(futures.ThreadPoolExecutor(),
+                     compression=grpc.Compression.Gzip)
+```
+
+#### For an individual RPC
+
+```python
+def SayHello(self, request, context):
+    context.set_response_compression(grpc.Compression.NoCompression)
+    return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
+```
+
+Setting the compression method for an individual RPC will override any setting
+supplied at server creation time.
diff --git a/examples/python/compression/client.py b/examples/python/compression/client.py
new file mode 100644
index 0000000..444f14c
--- /dev/null
+++ b/examples/python/compression/client.py
@@ -0,0 +1,76 @@
+# Copyright 2019 the 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.
+"""An example of compression on the client side with gRPC."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import argparse
+import logging
+import grpc
+
+from examples import helloworld_pb2
+from examples import helloworld_pb2_grpc
+
+_DESCRIPTION = 'A client capable of compression.'
+_COMPRESSION_OPTIONS = {
+    "none": grpc.Compression.NoCompression,
+    "deflate": grpc.Compression.Deflate,
+    "gzip": grpc.Compression.Gzip,
+}
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def run_client(channel_compression, call_compression, target):
+    with grpc.insecure_channel(
+            target, compression=channel_compression) as channel:
+        stub = helloworld_pb2_grpc.GreeterStub(channel)
+        response = stub.SayHello(
+            helloworld_pb2.HelloRequest(name='you'),
+            compression=call_compression,
+            wait_for_ready=True)
+        print("Response: {}".format(response))
+
+
+def main():
+    parser = argparse.ArgumentParser(description=_DESCRIPTION)
+    parser.add_argument(
+        '--channel_compression',
+        default='none',
+        nargs='?',
+        choices=_COMPRESSION_OPTIONS.keys(),
+        help='The compression method to use for the channel.')
+    parser.add_argument(
+        '--call_compression',
+        default='none',
+        nargs='?',
+        choices=_COMPRESSION_OPTIONS.keys(),
+        help='The compression method to use for an individual call.')
+    parser.add_argument(
+        '--server',
+        default='localhost:50051',
+        type=str,
+        nargs='?',
+        help='The host-port pair at which to reach the server.')
+    args = parser.parse_args()
+    channel_compression = _COMPRESSION_OPTIONS[args.channel_compression]
+    call_compression = _COMPRESSION_OPTIONS[args.call_compression]
+    run_client(channel_compression, call_compression, args.server)
+
+
+if __name__ == "__main__":
+    logging.basicConfig()
+    main()
diff --git a/examples/python/compression/server.py b/examples/python/compression/server.py
new file mode 100644
index 0000000..bc13e60
--- /dev/null
+++ b/examples/python/compression/server.py
@@ -0,0 +1,109 @@
+# Copyright 2019 the 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.
+"""An example of compression on the server side with gRPC."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+from concurrent import futures
+import argparse
+import logging
+import threading
+import time
+import grpc
+
+from examples import helloworld_pb2
+from examples import helloworld_pb2_grpc
+
+_DESCRIPTION = 'A server capable of compression.'
+_COMPRESSION_OPTIONS = {
+    "none": grpc.Compression.NoCompression,
+    "deflate": grpc.Compression.Deflate,
+    "gzip": grpc.Compression.Gzip,
+}
+_LOGGER = logging.getLogger(__name__)
+
+_SERVER_HOST = 'localhost'
+_ONE_DAY_IN_SECONDS = 60 * 60 * 24
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+    def __init__(self, no_compress_every_n):
+        super(Greeter, self).__init__()
+        self._no_compress_every_n = 0
+        self._request_counter = 0
+        self._counter_lock = threading.RLock()
+
+    def _should_suppress_compression(self):
+        suppress_compression = False
+        with self._counter_lock:
+            if self._no_compress_every_n and self._request_counter % self._no_compress_every_n == 0:
+                suppress_compression = True
+            self._request_counter += 1
+        return suppress_compression
+
+    def SayHello(self, request, context):
+        if self._should_suppress_compression():
+            context.set_response_compression(grpc.Compression.NoCompression)
+        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
+
+
+def run_server(server_compression, no_compress_every_n, port):
+    server = grpc.server(
+        futures.ThreadPoolExecutor(),
+        compression=server_compression,
+        options=(('grpc.so_reuseport', 1),))
+    helloworld_pb2_grpc.add_GreeterServicer_to_server(
+        Greeter(no_compress_every_n), server)
+    address = '{}:{}'.format(_SERVER_HOST, port)
+    server.add_insecure_port(address)
+    server.start()
+    print("Server listening at '{}'".format(address))
+    try:
+        while True:
+            time.sleep(_ONE_DAY_IN_SECONDS)
+    except KeyboardInterrupt:
+        server.stop(None)
+
+
+def main():
+    parser = argparse.ArgumentParser(description=_DESCRIPTION)
+    parser.add_argument(
+        '--server_compression',
+        default='none',
+        nargs='?',
+        choices=_COMPRESSION_OPTIONS.keys(),
+        help='The default compression method for the server.')
+    parser.add_argument(
+        '--no_compress_every_n',
+        type=int,
+        default=0,
+        nargs='?',
+        help='If set, every nth reply will be uncompressed.')
+    parser.add_argument(
+        '--port',
+        type=int,
+        default=50051,
+        nargs='?',
+        help='The port on which the server will listen.')
+    args = parser.parse_args()
+    run_server(_COMPRESSION_OPTIONS[args.server_compression],
+               args.no_compress_every_n, args.port)
+
+
+if __name__ == "__main__":
+    logging.basicConfig()
+    main()
diff --git a/examples/python/compression/test/compression_example_test.py b/examples/python/compression/test/compression_example_test.py
new file mode 100644
index 0000000..7d25379
--- /dev/null
+++ b/examples/python/compression/test/compression_example_test.py
@@ -0,0 +1,62 @@
+# Copyright 2019 the 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.
+"""Test for compression example."""
+
+import contextlib
+import os
+import socket
+import subprocess
+import unittest
+
+_BINARY_DIR = os.path.realpath(
+    os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
+_SERVER_PATH = os.path.join(_BINARY_DIR, 'server')
+_CLIENT_PATH = os.path.join(_BINARY_DIR, 'client')
+
+
+@contextlib.contextmanager
+def _get_port():
+    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
+    if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 0:
+        raise RuntimeError("Failed to set SO_REUSEPORT.")
+    sock.bind(('', 0))
+    try:
+        yield sock.getsockname()[1]
+    finally:
+        sock.close()
+
+
+class CompressionExampleTest(unittest.TestCase):
+
+    def test_compression_example(self):
+        with _get_port() as test_port:
+            server_process = subprocess.Popen((_SERVER_PATH, '--port',
+                                               str(test_port),
+                                               '--server_compression', 'gzip'))
+            try:
+                server_target = 'localhost:{}'.format(test_port)
+                client_process = subprocess.Popen(
+                    (_CLIENT_PATH, '--server', server_target,
+                     '--channel_compression', 'gzip'))
+                client_return_code = client_process.wait()
+                self.assertEqual(0, client_return_code)
+                self.assertIsNone(server_process.poll())
+            finally:
+                server_process.kill()
+                server_process.wait()
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)
diff --git a/examples/python/multiprocessing/BUILD b/examples/python/multiprocessing/BUILD
index 0e135f4..f9fa659 100644
--- a/examples/python/multiprocessing/BUILD
+++ b/examples/python/multiprocessing/BUILD
@@ -36,7 +36,7 @@
         "//src/python/grpcio/grpc:grpcio",
         ":prime_proto_pb2",
     ],
-    default_python_version = "PY3",
+    srcs_version = "PY3",
 )
 
 py_binary(
@@ -50,7 +50,7 @@
         "//conditions:default": [requirement("futures")],
         "//:python3": [],
     }),
-    default_python_version = "PY3",
+    srcs_version = "PY3",
 )
 
 py_test(
diff --git a/examples/python/multiprocessing/server.py b/examples/python/multiprocessing/server.py
index a05eb9e..b1e5951 100644
--- a/examples/python/multiprocessing/server.py
+++ b/examples/python/multiprocessing/server.py
@@ -87,7 +87,7 @@
     """Find and reserve a port for all subprocesses to use."""
     sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
-    if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) != 1:
+    if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 0:
         raise RuntimeError("Failed to set SO_REUSEPORT.")
     sock.bind(('', 0))
     try:
diff --git a/grpc.gemspec b/grpc.gemspec
index fc90a35..11469a3 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -13,7 +13,7 @@
   s.description   = 'Send RPCs from Ruby using GRPC'
   s.license       = 'Apache-2.0'
 
-  s.required_ruby_version = '>= 2.0.0'
+  s.required_ruby_version = '>= 2.3.0'
 
   s.files = %w( Makefile .yardopts )
   s.files += %w( etc/roots.pem )
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 00036d8..e0deed2 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -128,6 +128,10 @@
 
   void ShutdownLocked() override;
 
+  void AttemptToConnectUsingLatestUpdateArgsLocked();
+
+  // Lateset update args.
+  UpdateArgs latest_update_args_;
   // All our subchannels.
   OrphanablePtr<PickFirstSubchannelList> subchannel_list_;
   // Latest pending subchannel list.
@@ -167,18 +171,7 @@
   if (shutdown_) return;
   if (idle_) {
     idle_ = false;
-    if (subchannel_list_ == nullptr ||
-        subchannel_list_->num_subchannels() == 0) {
-      grpc_error* error = grpc_error_set_int(
-          GRPC_ERROR_CREATE_FROM_STATIC_STRING("No addresses to connect to"),
-          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
-      channel_control_helper()->UpdateState(
-          GRPC_CHANNEL_TRANSIENT_FAILURE,
-          UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
-    } else {
-      subchannel_list_->subchannel(0)
-          ->CheckConnectivityStateAndStartWatchingLocked();
-    }
+    AttemptToConnectUsingLatestUpdateArgsLocked();
   }
 }
 
@@ -189,36 +182,26 @@
   }
 }
 
-void PickFirst::UpdateLocked(UpdateArgs args) {
-  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
-    gpr_log(GPR_INFO,
-            "Pick First %p received update with %" PRIuPTR " addresses", this,
-            args.addresses.size());
-  }
-  grpc_arg new_arg = grpc_channel_arg_integer_create(
-      const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
-  grpc_channel_args* new_args =
-      grpc_channel_args_copy_and_add(args.args, &new_arg, 1);
+void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
+  // Create a subchannel list from the latest_update_args_.
   auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>(
-      this, &grpc_lb_pick_first_trace, args.addresses, combiner(), *new_args);
-  grpc_channel_args_destroy(new_args);
+      this, &grpc_lb_pick_first_trace, latest_update_args_.addresses,
+      combiner(), *latest_update_args_.args);
+  // Empty update or no valid subchannels.
   if (subchannel_list->num_subchannels() == 0) {
-    // Empty update or no valid subchannels. Unsubscribe from all current
-    // subchannels.
+    // Unsubscribe from all current subchannels.
     subchannel_list_ = std::move(subchannel_list);  // Empty list.
     selected_ = nullptr;
     // If not idle, put the channel in TRANSIENT_FAILURE.
     // (If we are idle, then this will happen in ExitIdleLocked() if we
     // haven't gotten a non-empty update by the time the application tries
     // to start a new call.)
-    if (!idle_) {
-      grpc_error* error = grpc_error_set_int(
-          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
-          GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
-      channel_control_helper()->UpdateState(
-          GRPC_CHANNEL_TRANSIENT_FAILURE,
-          UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
-    }
+    grpc_error* error =
+        grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
+                           GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+    channel_control_helper()->UpdateState(
+        GRPC_CHANNEL_TRANSIENT_FAILURE,
+        UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
     return;
   }
   // If one of the subchannels in the new list is already in state
@@ -226,8 +209,6 @@
   // currently selected subchannel is also present in the update.  It
   // can also happen if one of the subchannels in the update is already
   // in the global subchannel pool because it's in use by another channel.
-  // TODO(roth): If we're in IDLE state, we should probably defer this
-  // check and instead do it in ExitIdleLocked().
   for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
     PickFirstSubchannelData* sd = subchannel_list->subchannel(i);
     grpc_connectivity_state state = sd->CheckConnectivityStateLocked();
@@ -239,10 +220,6 @@
       // not have contained the currently selected subchannel), drop
       // it, so that it doesn't override what we've done here.
       latest_pending_subchannel_list_.reset();
-      // Make sure that subsequent calls to ExitIdleLocked() don't cause
-      // us to start watching a subchannel other than the one we've
-      // selected.
-      idle_ = false;
       return;
     }
   }
@@ -252,13 +229,11 @@
     subchannel_list_ = std::move(subchannel_list);
     // If we're not in IDLE state, start trying to connect to the first
     // subchannel in the new list.
-    if (!idle_) {
-      // Note: No need to use CheckConnectivityStateAndStartWatchingLocked()
-      // here, since we've already checked the initial connectivity
-      // state of all subchannels above.
-      subchannel_list_->subchannel(0)->StartConnectivityWatchLocked();
-      subchannel_list_->subchannel(0)->subchannel()->AttemptToConnect();
-    }
+    // Note: No need to use CheckConnectivityStateAndStartWatchingLocked()
+    // here, since we've already checked the initial connectivity
+    // state of all subchannels above.
+    subchannel_list_->subchannel(0)->StartConnectivityWatchLocked();
+    subchannel_list_->subchannel(0)->subchannel()->AttemptToConnect();
   } else {
     // We do have a selected subchannel (which means it's READY), so keep
     // using it until one of the subchannels in the new list reports READY.
@@ -274,16 +249,35 @@
     latest_pending_subchannel_list_ = std::move(subchannel_list);
     // If we're not in IDLE state, start trying to connect to the first
     // subchannel in the new list.
-    if (!idle_) {
-      // Note: No need to use CheckConnectivityStateAndStartWatchingLocked()
-      // here, since we've already checked the initial connectivity
-      // state of all subchannels above.
-      latest_pending_subchannel_list_->subchannel(0)
-          ->StartConnectivityWatchLocked();
-      latest_pending_subchannel_list_->subchannel(0)
-          ->subchannel()
-          ->AttemptToConnect();
-    }
+    // Note: No need to use CheckConnectivityStateAndStartWatchingLocked()
+    // here, since we've already checked the initial connectivity
+    // state of all subchannels above.
+    latest_pending_subchannel_list_->subchannel(0)
+        ->StartConnectivityWatchLocked();
+    latest_pending_subchannel_list_->subchannel(0)
+        ->subchannel()
+        ->AttemptToConnect();
+  }
+}
+
+void PickFirst::UpdateLocked(UpdateArgs args) {
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
+    gpr_log(GPR_INFO,
+            "Pick First %p received update with %" PRIuPTR " addresses", this,
+            args.addresses.size());
+  }
+  // Update the latest_update_args_
+  grpc_arg new_arg = grpc_channel_arg_integer_create(
+      const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
+  const grpc_channel_args* new_args =
+      grpc_channel_args_copy_and_add(args.args, &new_arg, 1);
+  GPR_SWAP(const grpc_channel_args*, new_args, args.args);
+  grpc_channel_args_destroy(new_args);
+  latest_update_args_ = std::move(args);
+  // If we are not in idle, start connection attempt immediately.
+  // Otherwise, we defer the attempt into ExitIdleLocked().
+  if (!idle_) {
+    AttemptToConnectUsingLatestUpdateArgsLocked();
   }
 }
 
@@ -338,10 +332,12 @@
         // also set the channel state to IDLE. The reason is that if the new
         // state is TRANSIENT_FAILURE due to a GOAWAY reception we don't want
         // to connect to the re-resolved backends until we leave IDLE state.
+        // TODO(qianchengz): We may want to request re-resolution in
+        // ExitIdleLocked().
         p->idle_ = true;
         p->channel_control_helper()->RequestReresolution();
         p->selected_ = nullptr;
-        CancelConnectivityWatchLocked("selected subchannel failed; going IDLE");
+        p->subchannel_list_.reset();
         p->channel_control_helper()->UpdateState(
             GRPC_CHANNEL_IDLE, UniquePtr<SubchannelPicker>(New<QueuePicker>(
                                    p->Ref(DEBUG_LOCATION, "QueuePicker"))));
@@ -454,6 +450,11 @@
   if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
     gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, subchannel());
   }
+  for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) {
+    if (i != Index()) {
+      subchannel_list()->subchannel(i)->ShutdownLocked();
+    }
+  }
 }
 
 void PickFirst::PickFirstSubchannelData::
diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc
index 4ef6c1f..d014460 100644
--- a/src/core/ext/filters/http/client/http_client_filter.cc
+++ b/src/core/ext/filters/http/client/http_client_filter.cc
@@ -558,7 +558,7 @@
 
   tmp = gpr_strvec_flatten(&v, nullptr);
   gpr_strvec_destroy(&v);
-  result = grpc_slice_intern(grpc_slice_from_static_string(tmp));
+  result = grpc_slice_intern(grpc_slice_from_static_string_internal(tmp));
   gpr_free(tmp);
 
   return result;
diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc
index 85b30bc..4bd666e 100644
--- a/src/core/ext/filters/http/client_authority_filter.cc
+++ b/src/core/ext/filters/http/client_authority_filter.cc
@@ -101,8 +101,8 @@
     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
         "GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string");
   }
-  chand->default_authority =
-      grpc_slice_intern(grpc_slice_from_static_string(default_authority_str));
+  chand->default_authority = grpc_slice_intern(
+      grpc_slice_from_static_string_internal(default_authority_str));
   chand->default_authority_mdelem = grpc_mdelem_create(
       GRPC_MDSTR_AUTHORITY, chand->default_authority, nullptr);
   GPR_ASSERT(!args->is_last);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
index 7d5c39e..8db0c96 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
@@ -670,7 +670,7 @@
     str->copied = true;
     str->data.referenced = grpc_empty_slice();
   } else if (intern) {
-    s = grpc_slice_intern(grpc_slice_from_static_buffer(
+    s = grpc_slice_intern(grpc_slice_from_static_buffer_internal(
         str->data.copied.str, str->data.copied.length));
   } else {
     s = grpc_slice_from_copied_buffer(str->data.copied.str,
@@ -1496,14 +1496,14 @@
 
 static bool is_binary_literal_header(grpc_chttp2_hpack_parser* p) {
   /* We know that either argument here is a reference counter slice.
-   * 1. If a result of grpc_slice_from_static_buffer, the refcount is set to
-   *    NoopRefcount.
+   * 1. If a result of grpc_slice_from_static_buffer_internal, the refcount is
+   *    set to kNoopRefcount.
    * 2. If it's p->key.data.referenced, then p->key.copied was set to false,
    *    which occurs in begin_parse_string() - where the refcount is set to
    *    p->current_slice_refcount, which is not null. */
   return grpc_is_refcounted_slice_binary_header(
-      p->key.copied ? grpc_slice_from_static_buffer(p->key.data.copied.str,
-                                                    p->key.data.copied.length)
+      p->key.copied ? grpc_slice_from_static_buffer_internal(
+                          p->key.data.copied.str, p->key.data.copied.length)
                     : p->key.data.referenced);
 }
 
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.cc b/src/core/ext/transport/chttp2/transport/hpack_table.cc
index f9e97cc..9d1ac4b 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.cc
@@ -29,6 +29,7 @@
 
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gpr/murmur_hash.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/validate_metadata.h"
 #include "src/core/lib/transport/static_metadata.h"
 
@@ -182,9 +183,10 @@
   memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
   for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
     tbl->static_ents[i - 1] = grpc_mdelem_from_slices(
-        grpc_slice_intern(grpc_slice_from_static_string(static_table[i].key)),
         grpc_slice_intern(
-            grpc_slice_from_static_string(static_table[i].value)));
+            grpc_slice_from_static_string_internal(static_table[i].key)),
+        grpc_slice_intern(
+            grpc_slice_from_static_string_internal(static_table[i].value)));
   }
 }
 
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 8da8985..8cb9ac4 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -1203,7 +1203,7 @@
  */
 void grpc_inproc_transport_init(void) {
   grpc_core::ExecCtx exec_ctx;
-  g_empty_slice = grpc_slice_from_static_buffer(nullptr, 0);
+  g_empty_slice = grpc_slice_from_static_buffer_internal(nullptr, 0);
 
   grpc_slice key_tmp = grpc_slice_from_static_string(":path");
   g_fake_path_key = grpc_slice_intern(key_tmp);
diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc
index ebec9dc..eb44c9a 100644
--- a/src/core/lib/iomgr/error.cc
+++ b/src/core/lib/iomgr/error.cc
@@ -447,13 +447,17 @@
 typedef struct {
   grpc_status_code code;
   const char* msg;
+  size_t len;
 } special_error_status_map;
-static const special_error_status_map error_status_map[] = {
-    {GRPC_STATUS_OK, ""},                               // GRPC_ERROR_NONE
-    {GRPC_STATUS_INVALID_ARGUMENT, ""},                 // GRPC_ERROR_RESERVED_1
-    {GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},  // GRPC_ERROR_OOM
-    {GRPC_STATUS_INVALID_ARGUMENT, ""},                 // GRPC_ERROR_RESERVED_2
-    {GRPC_STATUS_CANCELLED, "Cancelled"},               // GRPC_ERROR_CANCELLED
+
+const special_error_status_map error_status_map[] = {
+    {GRPC_STATUS_OK, "", 0},                // GRPC_ERROR_NONE
+    {GRPC_STATUS_INVALID_ARGUMENT, "", 0},  // GRPC_ERROR_RESERVED_1
+    {GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory",
+     strlen("Out of memory")},              // GRPC_ERROR_OOM
+    {GRPC_STATUS_INVALID_ARGUMENT, "", 0},  // GRPC_ERROR_RESERVED_2
+    {GRPC_STATUS_CANCELLED, "Cancelled",
+     strlen("Cancelled")},  // GRPC_ERROR_CANCELLED
 };
 
 bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) {
@@ -483,8 +487,12 @@
                         grpc_slice* str) {
   if (grpc_error_is_special(err)) {
     if (which != GRPC_ERROR_STR_GRPC_MESSAGE) return false;
-    *str = grpc_slice_from_static_string(
-        error_status_map[reinterpret_cast<size_t>(err)].msg);
+    const special_error_status_map& msg =
+        error_status_map[reinterpret_cast<size_t>(err)];
+    str->refcount = &grpc_core::kNoopRefcount;
+    str->data.refcounted.bytes =
+        reinterpret_cast<uint8_t*>(const_cast<char*>(msg.msg));
+    str->data.refcounted.length = msg.len;
     return true;
   }
   uint8_t slot = err->strs[which];
diff --git a/src/core/lib/slice/slice.cc b/src/core/lib/slice/slice.cc
index eebf66b..5786251 100644
--- a/src/core/lib/slice/slice.cc
+++ b/src/core/lib/slice/slice.cc
@@ -66,32 +66,13 @@
   }
 }
 
+namespace grpc_core {
+
 /* grpc_slice_from_static_string support structure - a refcount that does
    nothing */
-static grpc_slice_refcount NoopRefcount =
-    grpc_slice_refcount(grpc_slice_refcount::Type::NOP);
-
-size_t grpc_slice_memory_usage(grpc_slice s) {
-  if (s.refcount == nullptr || s.refcount == &NoopRefcount) {
-    return 0;
-  } else {
-    return s.data.refcounted.length;
-  }
-}
-
-grpc_slice grpc_slice_from_static_buffer(const void* s, size_t len) {
-  grpc_slice slice;
-  slice.refcount = &NoopRefcount;
-  slice.data.refcounted.bytes = (uint8_t*)s;
-  slice.data.refcounted.length = len;
-  return slice;
-}
-
-grpc_slice grpc_slice_from_static_string(const char* s) {
-  return grpc_slice_from_static_buffer(s, strlen(s));
-}
-
-namespace grpc_core {
+grpc_slice_refcount kNoopRefcount(grpc_slice_refcount::Type::NOP);
+static_assert(std::is_trivially_destructible<decltype(kNoopRefcount)>::value,
+              "kNoopRefcount must be trivially destructible.");
 
 /* grpc_slice_new support structures - we create a refcount object extended
    with the user provided data pointer & destroy function */
@@ -122,6 +103,22 @@
 
 }  // namespace grpc_core
 
+size_t grpc_slice_memory_usage(grpc_slice s) {
+  if (s.refcount == nullptr || s.refcount == &grpc_core::kNoopRefcount) {
+    return 0;
+  } else {
+    return s.data.refcounted.length;
+  }
+}
+
+grpc_slice grpc_slice_from_static_buffer(const void* s, size_t len) {
+  return grpc_slice_from_static_buffer_internal(s, len);
+}
+
+grpc_slice grpc_slice_from_static_string(const char* s) {
+  return grpc_slice_from_static_buffer_internal(s, strlen(s));
+}
+
 grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
                                          void (*destroy)(void*),
                                          void* user_data) {
@@ -375,10 +372,10 @@
       switch (ref_whom) {
         case GRPC_SLICE_REF_TAIL:
           tail.refcount = source->refcount->sub_refcount();
-          source->refcount = &NoopRefcount;
+          source->refcount = &grpc_core::kNoopRefcount;
           break;
         case GRPC_SLICE_REF_HEAD:
-          tail.refcount = &NoopRefcount;
+          tail.refcount = &grpc_core::kNoopRefcount;
           source->refcount = source->refcount->sub_refcount();
           break;
         case GRPC_SLICE_REF_BOTH:
diff --git a/src/core/lib/slice/slice_internal.h b/src/core/lib/slice/slice_internal.h
index c6943fe..54badeb 100644
--- a/src/core/lib/slice/slice_internal.h
+++ b/src/core/lib/slice/slice_internal.h
@@ -171,6 +171,8 @@
 
 namespace grpc_core {
 
+extern grpc_slice_refcount kNoopRefcount;
+
 struct InternedSliceRefcount {
   static void Destroy(void* arg) {
     auto* rc = static_cast<InternedSliceRefcount*>(arg);
@@ -312,4 +314,17 @@
 // 0. All other slices will return the size of the allocated chars.
 size_t grpc_slice_memory_usage(grpc_slice s);
 
+inline grpc_slice grpc_slice_from_static_buffer_internal(const void* s,
+                                                         size_t len) {
+  grpc_slice slice;
+  slice.refcount = &grpc_core::kNoopRefcount;
+  slice.data.refcounted.bytes = (uint8_t*)s;
+  slice.data.refcounted.length = len;
+  return slice;
+}
+
+inline grpc_slice grpc_slice_from_static_string_internal(const char* s) {
+  return grpc_slice_from_static_buffer_internal(s, strlen(s));
+}
+
 #endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */
diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc
index eb4e8c3..5be98c9 100644
--- a/src/core/lib/transport/error_utils.cc
+++ b/src/core/lib/transport/error_utils.cc
@@ -22,6 +22,7 @@
 
 #include <grpc/support/string_util.h>
 #include "src/core/lib/iomgr/error_internal.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/status_conversion.h"
 
 static grpc_error* recursively_find_error_with_field(grpc_error* error,
@@ -52,7 +53,15 @@
   if (GPR_LIKELY(error == GRPC_ERROR_NONE)) {
     if (code != nullptr) *code = GRPC_STATUS_OK;
     if (slice != nullptr) {
-      grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, slice);
+      // Normally, we call grpc_error_get_str(
+      //   error, GRPC_ERROR_STR_GRPC_MESSAGE, slice).
+      // We can fastpath since we know that:
+      // 1) Error is null
+      // 2) which == GRPC_ERROR_STR_GRPC_MESSAGE
+      // 3) The resulting slice is statically known.
+      // 4) Said resulting slice is of length 0 ("").
+      // This means 3 movs, instead of 10s of instructions and a strlen.
+      *slice = grpc_slice_from_static_string_internal("");
     }
     if (http_error != nullptr) {
       *http_error = GRPC_HTTP2_NO_ERROR;
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index 3cef031..4b96850 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -348,10 +348,11 @@
          free an interned md at any time: it's unsafe from this point on to
          access it so we read the hash now. */
       uint32_t hash = md->hash();
-      if (GPR_UNLIKELY(md->Unref())) {
 #ifndef NDEBUG
+      if (GPR_UNLIKELY(md->Unref(file, line))) {
         grpc_mdelem_on_final_unref(storage, md, hash, file, line);
 #else
+      if (GPR_UNLIKELY(md->Unref())) {
         grpc_mdelem_on_final_unref(storage, md, hash);
 #endif
       }
diff --git "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec" "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
index e9b5645..939078d 100644
--- "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
+++ "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
@@ -101,7 +101,7 @@
   s.preserve_paths = plugin
 
   # Restrict the protoc version to the one supported by this plugin.
-  s.dependency '!ProtoCompiler', '3.7.0'
+  s.dependency '!ProtoCompiler', '3.8.0'
   # For the Protobuf dependency not to complain:
   s.ios.deployment_target = '7.0'
   s.osx.deployment_target = '10.9'
diff --git "a/src/objective-c/\041ProtoCompiler.podspec" "b/src/objective-c/\041ProtoCompiler.podspec"
index 58d74be..d8ce4d8 100644
--- "a/src/objective-c/\041ProtoCompiler.podspec"
+++ "b/src/objective-c/\041ProtoCompiler.podspec"
@@ -36,7 +36,7 @@
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler'
-  v = '3.7.0'
+  v = '3.8.0'
   s.version  = v
   s.summary  = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
   s.description = <<-DESC
diff --git a/src/objective-c/tests/UnitTests/GRPCClientTests.m b/src/objective-c/tests/UnitTests/GRPCClientTests.m
index 9416416..bcd87c1 100644
--- a/src/objective-c/tests/UnitTests/GRPCClientTests.m
+++ b/src/objective-c/tests/UnitTests/GRPCClientTests.m
@@ -37,10 +37,14 @@
 
 #define TEST_TIMEOUT 16
 
-static NSString *const kHostAddress = @"localhost:5050";
+// The server address is derived from preprocessor macro, which is
+// in turn derived from environment variable of the same name.
+#define NSStringize_helper(x) #x
+#define NSStringize(x) @NSStringize_helper(x)
+static NSString *const kHostAddress = NSStringize(HOST_PORT_LOCAL);
 static NSString *const kPackage = @"grpc.testing";
 static NSString *const kService = @"TestService";
-static NSString *const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
+static NSString *const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE);
 
 static GRPCProtoMethod *kInexistentMethod;
 static GRPCProtoMethod *kEmptyCallMethod;
diff --git a/src/objective-c/tests/run_one_test.sh b/src/objective-c/tests/run_one_test.sh
old mode 100644
new mode 100755
index 04cba0e..b74107e
--- a/src/objective-c/tests/run_one_test.sh
+++ b/src/objective-c/tests/run_one_test.sh
@@ -45,10 +45,18 @@
 
 XCODEBUILD_FILTER='(^CompileC |^Ld |^ *[^ ]*clang |^ *cd |^ *export |^Libtool |^ *[^ ]*libtool |^CpHeader |^ *builtin-copy )'
 
+if [ -z $PLATFORM ]; then
+DESTINATION='name=iPhone 8'
+elif [ $PLATFORM == ios ]; then
+DESTINATION='name=iPhone 8'
+elif [ $PLATFORM == macos ]; then
+DESTINATION='platform=macOS'
+fi
+
 xcodebuild \
     -workspace Tests.xcworkspace \
-    -scheme SCHEME \
-    -destination name="iPhone 8" \
+    -scheme $SCHEME \
+    -destination "$DESTINATION" \
     HOST_PORT_LOCALSSL=localhost:$TLS_PORT \
     HOST_PORT_LOCAL=localhost:$PLAIN_PORT \
     HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi
index 59b3891..30fdf6a 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi
@@ -44,12 +44,12 @@
     pass
 
   struct grpc_custom_resolver_vtable:
-    grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res) except *
-    void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port) except *
+    grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res);
+    void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port);
 
   void grpc_custom_resolve_callback(grpc_custom_resolver* resolver,
                                     grpc_resolved_addresses* result,
-                                    grpc_error* error)
+                                    grpc_error* error);
 
 cdef extern from "src/core/lib/iomgr/tcp_custom.h":
   struct grpc_custom_socket:
@@ -67,25 +67,25 @@
   ctypedef void (*grpc_custom_close_callback)(grpc_custom_socket* socket)
 
   struct grpc_socket_vtable:
-      grpc_error* (*init)(grpc_custom_socket* socket, int domain) except *
+      grpc_error* (*init)(grpc_custom_socket* socket, int domain);
       void (*connect)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
-                      size_t len, grpc_custom_connect_callback cb) except *
-      void (*destroy)(grpc_custom_socket* socket) except *
-      void (*shutdown)(grpc_custom_socket* socket) except *
-      void (*close)(grpc_custom_socket* socket, grpc_custom_close_callback cb) except *
+                      size_t len, grpc_custom_connect_callback cb);
+      void (*destroy)(grpc_custom_socket* socket);
+      void (*shutdown)(grpc_custom_socket* socket);
+      void (*close)(grpc_custom_socket* socket, grpc_custom_close_callback cb);
       void (*write)(grpc_custom_socket* socket, grpc_slice_buffer* slices,
-                    grpc_custom_write_callback cb) except *
+                    grpc_custom_write_callback cb);
       void (*read)(grpc_custom_socket* socket, char* buffer, size_t length,
-                   grpc_custom_read_callback cb) except *
+                   grpc_custom_read_callback cb);
       grpc_error* (*getpeername)(grpc_custom_socket* socket,
-                                 const grpc_sockaddr* addr, int* len) except *
+                                 const grpc_sockaddr* addr, int* len);
       grpc_error* (*getsockname)(grpc_custom_socket* socket,
-                             const grpc_sockaddr* addr, int* len) except *
+                             const grpc_sockaddr* addr, int* len);
       grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
-                          size_t len, int flags) except *
-      grpc_error* (*listen)(grpc_custom_socket* socket) except *
+                          size_t len, int flags);
+      grpc_error* (*listen)(grpc_custom_socket* socket);
       void (*accept)(grpc_custom_socket* socket, grpc_custom_socket* client,
-                     grpc_custom_accept_callback cb) except *
+                     grpc_custom_accept_callback cb);
 
 cdef extern from "src/core/lib/iomgr/timer_custom.h":
   struct grpc_custom_timer:
@@ -94,17 +94,17 @@
      # We don't care about the rest of the fields
 
   struct grpc_custom_timer_vtable:
-    void (*start)(grpc_custom_timer* t) except *
-    void (*stop)(grpc_custom_timer* t) except *
+    void (*start)(grpc_custom_timer* t);
+    void (*stop)(grpc_custom_timer* t);
 
-  void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error)
+  void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error);
 
 cdef extern from "src/core/lib/iomgr/pollset_custom.h":
   struct grpc_custom_poller_vtable:
-    void (*init)() except *
-    void (*poll)(size_t timeout_ms) except *
-    void (*kick)() except *
-    void (*shutdown)() except *
+    void (*init)()
+    void (*poll)(size_t timeout_ms)
+    void (*kick)()
+    void (*shutdown)()
 
 cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
   void grpc_custom_iomgr_init(grpc_socket_vtable* socket,
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi
index f82fca2..a1618d0 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi
@@ -56,7 +56,7 @@
   c_addr.len = length
   return grpc_sockaddr_get_uri_scheme(&c_addr) == b'ipv4'
 
-cdef grpc_resolved_addresses* tuples_to_resolvaddr(tups) except *:
+cdef grpc_resolved_addresses* tuples_to_resolvaddr(tups):
   cdef grpc_resolved_addresses* addresses
   tups_set = set((tup[4][0], tup[4][1]) for tup in tups)
   addresses = <grpc_resolved_addresses*> malloc(sizeof(grpc_resolved_addresses))
@@ -84,7 +84,7 @@
     self.c_buffer = NULL
     self.len = 0
 
-cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) except * with gil:
+cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) with gil:
   sw = SocketWrapper()
   sw.c_socket = socket
   sw.sockopts = []
@@ -112,7 +112,7 @@
 
 cdef void socket_connect(grpc_custom_socket* socket, const grpc_sockaddr* addr,
                          size_t addr_len,
-                         grpc_custom_connect_callback cb) except * with gil:
+                         grpc_custom_connect_callback cb) with gil:
   py_socket = None
   socket_wrapper = <SocketWrapper>socket.impl
   socket_wrapper.connect_cb = cb
@@ -125,10 +125,10 @@
   socket_wrapper.socket = py_socket
   _spawn_greenlet(socket_connect_async, socket_wrapper, addr_tuple)
 
-cdef void socket_destroy(grpc_custom_socket* socket) except * with gil:
+cdef void socket_destroy(grpc_custom_socket* socket) with gil:
   cpython.Py_DECREF(<SocketWrapper>socket.impl)
 
-cdef void socket_shutdown(grpc_custom_socket* socket) except * with gil:
+cdef void socket_shutdown(grpc_custom_socket* socket) with gil:
   try:
     (<SocketWrapper>socket.impl).socket.shutdown(gevent_socket.SHUT_RDWR)
   except IOError as io_error:
@@ -136,7 +136,7 @@
       raise io_error
 
 cdef void socket_close(grpc_custom_socket* socket,
-                       grpc_custom_close_callback cb) except * with gil:
+                       grpc_custom_close_callback cb) with gil:
   socket_wrapper = (<SocketWrapper>socket.impl)
   if socket_wrapper.socket is not None:
     socket_wrapper.socket.close()
@@ -176,7 +176,7 @@
   socket_write_async_cython(socket_wrapper, write_bytes)
 
 cdef void socket_write(grpc_custom_socket* socket, grpc_slice_buffer* buffer,
-                       grpc_custom_write_callback cb) except * with gil:
+                       grpc_custom_write_callback cb) with gil:
   cdef char* start
   sw = <SocketWrapper>socket.impl
   sw.write_cb = cb
@@ -204,7 +204,7 @@
   socket_read_async_cython(socket_wrapper)
 
 cdef void socket_read(grpc_custom_socket* socket, char* buffer,
-                      size_t length, grpc_custom_read_callback cb) except * with gil:
+                      size_t length, grpc_custom_read_callback cb) with gil:
   sw = <SocketWrapper>socket.impl
   sw.read_cb = cb
   sw.c_buffer = buffer
@@ -213,7 +213,7 @@
 
 cdef grpc_error* socket_getpeername(grpc_custom_socket* socket,
                                     const grpc_sockaddr* addr,
-                                    int* length) except * with gil:
+                                    int* length) with gil:
   cdef char* src_buf
   peer = (<SocketWrapper>socket.impl).socket.getpeername()
 
@@ -226,7 +226,7 @@
 
 cdef grpc_error* socket_getsockname(grpc_custom_socket* socket,
                                     const grpc_sockaddr* addr,
-                                    int* length) except * with gil:
+                                    int* length) with gil:
   cdef char* src_buf
   cdef grpc_resolved_address c_addr
   if (<SocketWrapper>socket.impl).socket is None:
@@ -245,7 +245,7 @@
 
 cdef grpc_error* socket_bind(grpc_custom_socket* socket,
                              const grpc_sockaddr* addr,
-                             size_t len, int flags) except * with gil:
+                             size_t len, int flags) with gil:
   addr_tuple = sockaddr_to_tuple(addr, len)
   try:
     try:
@@ -262,7 +262,7 @@
   else:
     return grpc_error_none()
 
-cdef grpc_error* socket_listen(grpc_custom_socket* socket) except * with gil:
+cdef grpc_error* socket_listen(grpc_custom_socket* socket) with gil:
   (<SocketWrapper>socket.impl).socket.listen(50)
   return grpc_error_none()
 
@@ -292,7 +292,7 @@
   accept_callback_cython(s)
 
 cdef void socket_accept(grpc_custom_socket* socket, grpc_custom_socket* client,
-                        grpc_custom_accept_callback cb) except * with gil:
+                        grpc_custom_accept_callback cb) with gil:
   sw = <SocketWrapper>socket.impl
   sw.accepting_socket = client
   sw.accept_cb = cb
@@ -322,7 +322,7 @@
 def socket_resolve_async_python(resolve_wrapper):
   socket_resolve_async_cython(resolve_wrapper)
 
-cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) except * with gil:
+cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) with gil:
   rw = ResolveWrapper()
   rw.c_resolver = r
   rw.c_host = host
@@ -330,7 +330,7 @@
   _spawn_greenlet(socket_resolve_async_python, rw)
 
 cdef grpc_error* socket_resolve(char* host, char* port,
-                                grpc_resolved_addresses** res) except * with gil:
+                                grpc_resolved_addresses** res) with gil:
     try:
       result = gevent_socket.getaddrinfo(host, port)
       res[0] = tuples_to_resolvaddr(result)
@@ -360,13 +360,13 @@
     self.event.set()
     self.timer.stop()
 
-cdef void timer_start(grpc_custom_timer* t) except * with gil:
+cdef void timer_start(grpc_custom_timer* t) with gil:
   timer = TimerWrapper(t.timeout_ms / 1000.0)
   timer.c_timer = t
   t.timer = <void*>timer
   timer.start()
 
-cdef void timer_stop(grpc_custom_timer* t) except * with gil:
+cdef void timer_stop(grpc_custom_timer* t) with gil:
   time_wrapper = <object>t.timer
   time_wrapper.stop()
 
@@ -374,16 +374,16 @@
 ### pollset implementation ###
 ###############################
 
-cdef void init_loop() except * with gil:
+cdef void init_loop() with gil:
   pass
 
-cdef void destroy_loop() except * with gil:
+cdef void destroy_loop() with gil:
   g_pool.join()
 
-cdef void kick_loop() except * with gil:
+cdef void kick_loop() with gil:
   g_event.set()
 
-cdef void run_loop(size_t timeout_ms) except * with gil:
+cdef void run_loop(size_t timeout_ms) with gil:
     timeout = timeout_ms / 1000.0
     if timeout_ms > 0:
       g_event.wait(timeout)
diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template
index f8dd093..12862c8 100644
--- a/templates/grpc.gemspec.template
+++ b/templates/grpc.gemspec.template
@@ -15,7 +15,7 @@
     s.description   = 'Send RPCs from Ruby using GRPC'
     s.license       = 'Apache-2.0'
 
-    s.required_ruby_version = '>= 2.0.0'
+    s.required_ruby_version = '>= 2.3.0'
 
     s.files = %w( Makefile .yardopts )
     s.files += %w( etc/roots.pem )
diff --git "a/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template" "b/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
index 741f9b7..b2335ac 100644
--- "a/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
+++ "b/templates/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec.template"
@@ -103,7 +103,7 @@
     s.preserve_paths = plugin
 
     # Restrict the protoc version to the one supported by this plugin.
-    s.dependency '!ProtoCompiler', '3.7.0'
+    s.dependency '!ProtoCompiler', '3.8.0'
     # For the Protobuf dependency not to complain:
     s.ios.deployment_target = '7.0'
     s.osx.deployment_target = '10.9'
diff --git a/templates/tools/dockerfile/bazel.include b/templates/tools/dockerfile/bazel.include
index 2729360..adde6ed 100644
--- a/templates/tools/dockerfile/bazel.include
+++ b/templates/tools/dockerfile/bazel.include
@@ -2,7 +2,7 @@
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 0.24.1
+ENV BAZEL_VERSION 0.26.0
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py
index a4f3e4a..e390db9 100755
--- a/test/core/bad_client/gen_build_yaml.py
+++ b/test/core/bad_client/gen_build_yaml.py
@@ -27,12 +27,14 @@
 # maps test names to options
 BAD_CLIENT_TESTS = {
     'badreq': default_test_options,
+    'bad_streaming_id': default_test_options,
     'connection_prefix': default_test_options._replace(cpu_cost=0.2),
     'duplicate_header': default_test_options,
     'headers': default_test_options._replace(cpu_cost=0.2),
     'initial_settings_frame': default_test_options._replace(cpu_cost=0.2),
     'head_of_line_blocking': default_test_options,
     'large_metadata': default_test_options,
+    'out_of_bounds': default_test_options,
     'server_registered_method': default_test_options,
     'simple_request': default_test_options,
     'window_overflow': default_test_options,
diff --git a/test/core/bad_client/generate_tests.bzl b/test/core/bad_client/generate_tests.bzl
index da372dd..6fb53ee 100755
--- a/test/core/bad_client/generate_tests.bzl
+++ b/test/core/bad_client/generate_tests.bzl
@@ -25,12 +25,14 @@
 # maps test names to options
 BAD_CLIENT_TESTS = {
     'badreq': test_options(),
+    'bad_streaming_id': test_options(),
     'connection_prefix': test_options(),
     'duplicate_header': test_options(),
     'headers': test_options(),
     'initial_settings_frame': test_options(),
     'head_of_line_blocking': test_options(),
     'large_metadata': test_options(),
+    'out_of_bounds': test_options(),
     'server_registered_method': test_options(),
     'simple_request': test_options(),
     'window_overflow': test_options(),
diff --git a/test/core/bad_client/tests/bad_streaming_id.cc b/test/core/bad_client/tests/bad_streaming_id.cc
new file mode 100644
index 0000000..287db43
--- /dev/null
+++ b/test/core/bad_client/tests/bad_streaming_id.cc
@@ -0,0 +1,132 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <grpc/support/string_util.h>
+#include "src/core/lib/surface/server.h"
+#include "test/core/bad_client/bad_client.h"
+
+#define HEADER_FRAME_ID_1                                                  \
+  "\x00\x00\xc9\x01\x05\x00\x00\x00\x01" /* headers: generated from        \
+                                            simple_request.headers in this \
+                                            directory */                   \
+  "\x10\x05:path\x08/foo/bar"                                              \
+  "\x10\x07:scheme\x04http"                                                \
+  "\x10\x07:method\x04POST"                                                \
+  "\x10\x0a:authority\x09localhost"                                        \
+  "\x10\x0c"                                                               \
+  "content-type\x10"                                                       \
+  "application/grpc"                                                       \
+  "\x10\x14grpc-accept-encoding\x15"                                       \
+  "deflate,identity,gzip"                                                  \
+  "\x10\x02te\x08trailers"                                                 \
+  "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
+
+#define HEADER_FRAME_ID_2                                                  \
+  "\x00\x00\xc9\x01\x05\x00\x00\x00\x02" /* headers: generated from        \
+                                            simple_request.headers in this \
+                                            directory */                   \
+  "\x10\x05:path\x08/foo/bar"                                              \
+  "\x10\x07:scheme\x04http"                                                \
+  "\x10\x07:method\x04POST"                                                \
+  "\x10\x0a:authority\x09localhost"                                        \
+  "\x10\x0c"                                                               \
+  "content-type\x10"                                                       \
+  "application/grpc"                                                       \
+  "\x10\x14grpc-accept-encoding\x15"                                       \
+  "deflate,identity,gzip"                                                  \
+  "\x10\x02te\x08trailers"                                                 \
+  "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
+
+#define HEADER_FRAME_ID_3                                                  \
+  "\x00\x00\xc9\x01\x05\x00\x00\x00\x03" /* headers: generated from        \
+                                            simple_request.headers in this \
+                                            directory */                   \
+  "\x10\x05:path\x08/foo/bar"                                              \
+  "\x10\x07:scheme\x04http"                                                \
+  "\x10\x07:method\x04POST"                                                \
+  "\x10\x0a:authority\x09localhost"                                        \
+  "\x10\x0c"                                                               \
+  "content-type\x10"                                                       \
+  "application/grpc"                                                       \
+  "\x10\x14grpc-accept-encoding\x15"                                       \
+  "deflate,identity,gzip"                                                  \
+  "\x10\x02te\x08trailers"                                                 \
+  "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
+
+namespace {
+
+void verifier(grpc_server* server, grpc_completion_queue* cq,
+              void* registered_method) {
+  while (grpc_server_has_open_connections(server)) {
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)
+                   .type == GRPC_QUEUE_TIMEOUT);
+  }
+}
+
+TEST(BadStreamingId, RegularHeader) {
+  grpc_bad_client_arg args[2];
+  args[0] = connection_preface_arg;
+  args[1].client_validator = nullptr;
+  args[1].client_payload = HEADER_FRAME_ID_1;
+  args[1].client_payload_length = sizeof(HEADER_FRAME_ID_1) - 1;
+  grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT);
+}
+
+TEST(BadStreamingId, NonClientStreamId) {
+  grpc_bad_client_arg args[2];
+  args[0] = connection_preface_arg;
+  // send a header frame with non-client stream id 2
+  args[1].client_validator = nullptr;
+  args[1].client_payload = HEADER_FRAME_ID_2;
+  args[1].client_payload_length = sizeof(HEADER_FRAME_ID_2) - 1;
+  grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT);
+}
+
+TEST(BadStreamingId, ClosedStreamId) {
+  grpc_bad_client_arg args[4];
+  args[0] = connection_preface_arg;
+  // send a header frame with stream id 1
+  args[1].client_validator = nullptr;
+  args[1].client_payload = HEADER_FRAME_ID_1;
+  args[1].client_payload_length = sizeof(HEADER_FRAME_ID_1) - 1;
+  // send a header frame with stream id 3
+  args[2].client_validator = nullptr;
+  args[2].client_payload = HEADER_FRAME_ID_3;
+  args[2].client_payload_length = sizeof(HEADER_FRAME_ID_3) - 1;
+  // send a header frame with closed stream id 1 again
+  args[3].client_validator = nullptr;
+  args[3].client_payload = HEADER_FRAME_ID_1;
+  args[3].client_payload_length = sizeof(HEADER_FRAME_ID_1) - 1;
+  grpc_run_bad_client_test(verifier, args, 4, GRPC_BAD_CLIENT_DISCONNECT);
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  grpc_init();
+  grpc::testing::TestEnvironment env(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  int retval = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return retval;
+}
diff --git a/test/core/bad_client/tests/out_of_bounds.cc b/test/core/bad_client/tests/out_of_bounds.cc
new file mode 100644
index 0000000..b716e95
--- /dev/null
+++ b/test/core/bad_client/tests/out_of_bounds.cc
@@ -0,0 +1,112 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <grpc/support/string_util.h>
+#include "src/core/lib/surface/server.h"
+#include "test/core/bad_client/bad_client.h"
+
+#define APPEND_BUFFER(string, to_append) \
+  ((string).append((to_append), sizeof(to_append) - 1))
+
+namespace {
+
+void verifier(grpc_server* server, grpc_completion_queue* cq,
+              void* registered_method) {
+  while (grpc_server_has_open_connections(server)) {
+    GPR_ASSERT(grpc_completion_queue_next(
+                   cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)
+                   .type == GRPC_QUEUE_TIMEOUT);
+  }
+}
+
+void FrameVerifier(const std::string& attack_vector) {
+  grpc_bad_client_arg args[2];
+  args[0] = connection_preface_arg;
+  args[1].client_validator = nullptr;
+  args[1].client_payload = attack_vector.c_str();
+  args[1].client_payload_length = attack_vector.size();
+  grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT);
+}
+
+TEST(OutOfBounds, MaxFrameSizeDataFrame) {
+  std::string out_of_bounds_data;
+  // Send a data frame larger than 2^14
+  APPEND_BUFFER(out_of_bounds_data, "\x01\x00\x00\x00\x00\x00\x00\x00\x01");
+  out_of_bounds_data.append(1 << 16, 'a');
+  FrameVerifier(out_of_bounds_data);
+}
+
+TEST(OutOfBounds, BadSizePriorityFrame) {
+  std::string bad_size_priority_frame;
+  // Priority Frame should be a length of 5 octets
+  APPEND_BUFFER(bad_size_priority_frame,
+                "\x00\x00\x03\x02\x00\x00\x00\x00\x01"
+                "\x11\x11\x12");
+  FrameVerifier(bad_size_priority_frame);
+}
+
+TEST(OutOfBounds, BadSizeRstStream) {
+  std::string bad_size_rst_stream;
+  // Rst Stream Frame should have a length of 4 octets
+  APPEND_BUFFER(bad_size_rst_stream,
+                "\x00\x00\x02\x03\x00\x00\x00\x00\x01"
+                "\x11\x11");
+  FrameVerifier(bad_size_rst_stream);
+}
+
+TEST(OutOfBounds, BadSizeSettings) {
+  std::string bad_size_settings;
+  // Settings Frame should have a length which is a multiple of 6 octets
+  APPEND_BUFFER(bad_size_settings,
+                "\x00\x00\x05\x04\x00\x00\x00\x00\x00"
+                "\x11\x11\x11\x11\x11");
+  FrameVerifier(bad_size_settings);
+}
+
+TEST(OutOfBounds, BadSizePing) {
+  std::string bad_size_ping;
+  // Rst Stream Frame should have a length of 8 octets
+  APPEND_BUFFER(bad_size_ping,
+                "\x00\x00\x05\x06\x00\x00\x00\x00\x00"
+                "\x11\x11\x11\x11\x11");
+  FrameVerifier(bad_size_ping);
+}
+
+TEST(OutOfBounds, WindowUpdate) {
+  std::string bad_size_window_update;
+  // Window Update Frame should have a length of 4 octets
+  APPEND_BUFFER(bad_size_window_update,
+                "\x00\x00\x01\x08\x00\x00\x00\x00\x00"
+                "\x11");
+  FrameVerifier(bad_size_window_update);
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  grpc_init();
+  grpc::testing::TestEnvironment env(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  int retval = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return retval;
+}
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
index d229cc3..ab0ef0c 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -369,7 +369,6 @@
     name = "mock_test",
     srcs = ["mock_test.cc"],
     external_deps = [
-        "gmock",
         "gtest",
     ],
     deps = [
@@ -406,7 +405,6 @@
     name = "client_lb_end2end_test",
     srcs = ["client_lb_end2end_test.cc"],
     external_deps = [
-        "gmock",
         "gtest",
     ],
     deps = [
@@ -427,7 +425,6 @@
     name = "service_config_end2end_test",
     srcs = ["service_config_end2end_test.cc"],
     external_deps = [
-        "gmock",
         "gtest",
     ],
     deps = [
@@ -447,7 +444,6 @@
     name = "grpclb_end2end_test",
     srcs = ["grpclb_end2end_test.cc"],
     external_deps = [
-        "gmock",
         "gtest",
     ],
     deps = [
@@ -469,7 +465,6 @@
     name = "xds_end2end_test",
     srcs = ["xds_end2end_test.cc"],
     external_deps = [
-        "gmock",
         "gtest",
     ],
     deps = [
@@ -594,7 +589,6 @@
     srcs = ["server_load_reporting_end2end_test.cc"],
     external_deps = [
         "gtest",
-        "gmock",
     ],
     deps = [
         "//:grpcpp_server_load_reporting",
diff --git a/test/cpp/ext/filters/census/BUILD b/test/cpp/ext/filters/census/BUILD
index 78b27e2..452a84b 100644
--- a/test/cpp/ext/filters/census/BUILD
+++ b/test/cpp/ext/filters/census/BUILD
@@ -26,7 +26,6 @@
     ],
     external_deps = [
         "gtest",
-        "gmock",
         "opencensus-stats-test",
     ],
     language = "C++",
diff --git a/test/cpp/naming/BUILD b/test/cpp/naming/BUILD
index 7db435a..b91c0b8 100644
--- a/test/cpp/naming/BUILD
+++ b/test/cpp/naming/BUILD
@@ -37,7 +37,7 @@
 grpc_cc_test(
     name = "cancel_ares_query_test",
     srcs = ["cancel_ares_query_test.cc"],
-    external_deps = ["gmock"],
+    external_deps = ["gtest"],
     deps = [
         ":dns_test_util",
         "//:gpr",
diff --git a/test/cpp/naming/generate_resolver_component_tests.bzl b/test/cpp/naming/generate_resolver_component_tests.bzl
index bcc62f6..2ce61d0 100755
--- a/test/cpp/naming/generate_resolver_component_tests.bzl
+++ b/test/cpp/naming/generate_resolver_component_tests.bzl
@@ -23,7 +23,7 @@
             "address_sorting_test.cc",
         ],
         external_deps = [
-            "gmock",
+            "gtest",
         ],
         deps = [
             "//test/cpp/util:test_util%s" % unsecure_build_config_suffix,
@@ -43,7 +43,7 @@
             "resolver_component_test.cc",
         ],
         external_deps = [
-            "gmock",
+            "gtest",
         ],
         deps = [
             ":dns_test_util",
diff --git a/test/cpp/server/load_reporter/BUILD b/test/cpp/server/load_reporter/BUILD
index db5c932..633b6d8 100644
--- a/test/cpp/server/load_reporter/BUILD
+++ b/test/cpp/server/load_reporter/BUILD
@@ -35,7 +35,6 @@
     srcs = ["load_reporter_test.cc"],
     external_deps = [
         "gtest",
-        "gmock",
         "opencensus-stats-test",
     ],
     deps = [
diff --git a/third_party/googletest b/third_party/googletest
index ec44c6c..2fe3bd9 160000
--- a/third_party/googletest
+++ b/third_party/googletest
@@ -1 +1 @@
-Subproject commit ec44c6c1675c25b9827aacd08c02433cccde7780
+Subproject commit 2fe3bd994b3189899d93f1d5a881e725e046fdc2
diff --git a/third_party/gtest.BUILD b/third_party/gtest.BUILD
deleted file mode 100644
index f38bfd8..0000000
--- a/third_party/gtest.BUILD
+++ /dev/null
@@ -1,42 +0,0 @@
-cc_library(
-    name = "gtest",
-    srcs = [
-        "googletest/src/gtest-all.cc",
-    ],
-    hdrs = glob([
-        "googletest/include/**/*.h",
-        "googletest/src/*.cc",
-        "googletest/src/*.h",
-    ]),
-    includes = [
-        "googletest",
-        "googletest/include",
-    ],
-    linkstatic = 1,
-    visibility = [
-        "//visibility:public",
-    ],
-)
-
-cc_library(
-    name = "gmock",
-    srcs = [
-        "googlemock/src/gmock-all.cc"
-    ],
-    hdrs = glob([
-        "googlemock/include/**/*.h",
-        "googlemock/src/*.cc",
-        "googlemock/src/*.h"
-    ]),
-    includes = [
-        "googlemock",
-        "googlemock/include",
-    ],
-    deps = [
-        ":gtest",
-    ],
-    linkstatic = 1,
-    visibility = [
-        "//visibility:public",
-    ],
-)
diff --git a/tools/bazel b/tools/bazel
index bacfead..4f08d18 100755
--- a/tools/bazel
+++ b/tools/bazel
@@ -32,7 +32,7 @@
   exec -a "$0" "${BAZEL_REAL}" "$@"
 fi
 
-VERSION=0.24.1
+VERSION=0.26.0
 
 echo "INFO: Running bazel wrapper (see //tools/bazel for details), bazel version $VERSION will be used instead of system-wide bazel installation."
 
diff --git a/tools/bazel.rc b/tools/bazel.rc
index 9934749..4bd3a5d 100644
--- a/tools/bazel.rc
+++ b/tools/bazel.rc
@@ -51,6 +51,10 @@
 build:ubsan --copt=-fno-sanitize=function,vptr
 build:ubsan --linkopt=-fsanitize=undefined
 build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1:suppressions=test/core/util/ubsan_suppressions.txt
+# For some reasons, these two stopped being propagated, so, redeclaring them here.
+# That's a hack that needs to be removed once we understand what's going on.
+build:ubsan --copt=-DPB_FIELD_32BIT=1
+build:ubsan --copt=-DGRPC_PORT_ISOLATED_RUNTIME=1
 
 build:basicprof --strip=never
 build:basicprof --copt=-DNDEBUG
@@ -59,5 +63,5 @@
 build:basicprof --copt=-DGRPC_TIMERS_RDTSC
 
 build:python3 --python_path=python3
-build:python3 --force_python=PY3
+build:python3 --python_version=PY3
 build:python3 --action_env=PYTHON_BIN_PATH=python3
diff --git a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
index b53ffc2..0812b86 100644
--- a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
@@ -22,14 +22,14 @@
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
 RUN curl -sSL https://get.rvm.io | bash -s stable
 
-# Install Ruby 2.2
+# Install Ruby 2.3
 # Running the installation twice to work around docker issue when using overlay.
 # https://github.com/docker/docker/issues/10180
-RUN (/bin/bash -l -c "rvm install ruby-2.2.10") || (/bin/bash -l -c "rvm install ruby-2.2.10")
-RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
+RUN (/bin/bash -l -c "rvm install ruby-2.3.8") || (/bin/bash -l -c "rvm install ruby-2.3.8")
+RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
 RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
 RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
-RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
 RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
 
 RUN mkdir /var/local/jenkins
diff --git a/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
index 72235bf..fc4eabb 100644
--- a/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
@@ -20,12 +20,12 @@
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
 RUN curl -sSL https://get.rvm.io | bash -s stable
 
-# Install Ruby 2.2
-RUN /bin/bash -l -c "rvm install ruby-2.2.10"
-RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
+# Install Ruby 2.3
+RUN /bin/bash -l -c "rvm install ruby-2.3.8"
+RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
 RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
 RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
-RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
 RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
 
 RUN mkdir /var/local/jenkins
diff --git a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
index 3d688a8..73a4bd7 100644
--- a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
@@ -21,14 +21,14 @@
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
 RUN curl -sSL https://get.rvm.io | bash -s stable
 
-# Install Ruby 2.2
+# Install Ruby 2.3
 # Running the installation twice to work around docker issue when using overlay.
 # https://github.com/docker/docker/issues/10180
-RUN (/bin/bash -l -c "rvm install ruby-2.2.10") || (/bin/bash -l -c "rvm install ruby-2.2.10")
-RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
+RUN (/bin/bash -l -c "rvm install ruby-2.3.8") || (/bin/bash -l -c "rvm install ruby-2.3.8")
+RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
 RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
 RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
-RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
 RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
 
 RUN mkdir /var/local/jenkins
diff --git a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
index 8044adf..43c0ae5 100644
--- a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
@@ -26,12 +26,12 @@
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
 RUN curl -sSL https://get.rvm.io | bash -s stable
 
-# Install Ruby 2.2
-RUN /bin/bash -l -c "rvm install ruby-2.2.10"
-RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
+# Install Ruby 2.3
+RUN /bin/bash -l -c "rvm install ruby-2.3.8"
+RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
 RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
 RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
-RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
 RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
 
 RUN mkdir /var/local/jenkins
diff --git a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
index 848c5be..e077f68 100644
--- a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
@@ -14,6 +14,26 @@
 
 FROM fedora:22
 
-RUN yum clean all && yum update -y && yum install -y ruby findutils
+# Make yum work properly under docker when using overlay storage driver.
+# https://bugzilla.redhat.com/show_bug.cgi?id=1213602#c9
+# https://github.com/docker/docker/issues/10180
+RUN yum install -y yum-plugin-ovl
 
-RUN gem install bundler
+# distro-sync and install openssl, per https://github.com/fedora-cloud/docker-brew-fedora/issues/19
+RUN yum clean all && yum update -y && yum distro-sync -y && yum install -y openssl gnupg which findutils tar procps
+
+# Install rvm
+RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
+RUN curl -sSL https://get.rvm.io | bash -s stable
+
+# Install Ruby 2.3
+RUN /bin/bash -l -c "rvm install ruby-2.3.8"
+RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
+RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
+RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
+RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
+
+RUN mkdir /var/local/jenkins
+
+RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"
diff --git a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
index 47dd577..f586ae3 100644
--- a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
@@ -14,6 +14,26 @@
 
 FROM fedora:23
 
-RUN yum clean all && yum update -y && yum install -y ruby findutils
+# Make yum work properly under docker when using overlay storage driver.
+# https://bugzilla.redhat.com/show_bug.cgi?id=1213602#c9
+# https://github.com/docker/docker/issues/10180
+RUN yum install -y yum-plugin-ovl
 
-RUN gem install bundler
+# distro-sync and install openssl, per https://github.com/fedora-cloud/docker-brew-fedora/issues/19
+RUN yum clean all && yum update -y && yum distro-sync -y && yum install -y openssl gnupg which findutils tar procps
+
+# Install rvm
+RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
+RUN curl -sSL https://get.rvm.io | bash -s stable
+
+# Install Ruby 2.3
+RUN /bin/bash -l -c "rvm install ruby-2.3.8"
+RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
+RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
+RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
+RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
+RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
+
+RUN mkdir /var/local/jenkins
+
+RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"
diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile
deleted file mode 100644
index 337fc3b..0000000
--- a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2015 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-FROM debian:jessie
-
-# Install Git and basic packages.
-RUN apt-get update && apt-get install -y \
-  curl \
-  gcc && apt-get clean
-
-#==================
-# Ruby dependencies
-
-# Install rvm
-RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
-RUN \curl -sSL https://get.rvm.io | bash -s stable
-
-# Install Ruby 2.2
-RUN /bin/bash -l -c "rvm install ruby-2.2.10"
-RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
-RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
-RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
-RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
-RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
-
-RUN mkdir /var/local/jenkins
-
-# Define the default command.
-CMD ["bash"]
diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile
index df7a7a2..7e79033 100644
--- a/tools/dockerfile/test/bazel/Dockerfile
+++ b/tools/dockerfile/test/bazel/Dockerfile
@@ -52,7 +52,7 @@
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 0.24.1
+ENV BAZEL_VERSION 0.26.0
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile
index 9a080d0..ca786e2 100644
--- a/tools/dockerfile/test/sanity/Dockerfile
+++ b/tools/dockerfile/test/sanity/Dockerfile
@@ -98,7 +98,7 @@
 # Bazel installation
 
 # Must be in sync with tools/bazel
-ENV BAZEL_VERSION 0.24.1
+ENV BAZEL_VERSION 0.26.0
 
 # The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
 ENV DISABLE_BAZEL_WRAPPER 1
diff --git a/tools/remote_build/rbe_common.bazelrc b/tools/remote_build/rbe_common.bazelrc
index 63b49c5..6baaf24 100644
--- a/tools/remote_build/rbe_common.bazelrc
+++ b/tools/remote_build/rbe_common.bazelrc
@@ -84,4 +84,7 @@
 # TODO(jtattermusch): use more reasonable test timeout
 build:ubsan --test_timeout=3600
 # override the config-agnostic crosstool_top
+# how to update the bazel toolchain for ubsan:
+# - check for the latest released version in https://github.com/bazelbuild/bazel-toolchains/tree/master/configs/experimental/ubuntu16_04_clang
+# - you might need to update the bazel_toolchains dependency in grpc_deps.bzl
 build:ubsan --crosstool_top=@bazel_toolchains//configs/experimental/ubuntu16_04_clang/1.2/bazel_0.23.0/ubsan:toolchain
diff --git a/tools/run_tests/artifacts/distribtest_targets.py b/tools/run_tests/artifacts/distribtest_targets.py
index 1e86102..35a561e 100644
--- a/tools/run_tests/artifacts/distribtest_targets.py
+++ b/tools/run_tests/artifacts/distribtest_targets.py
@@ -340,14 +340,12 @@
         RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_4'),
         RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_5'),
         RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_6'),
-        # TODO(apolcyn): unskip these after upgrading the ruby versions
-        # of these dockerfiles to >= 2.3.
-        #   RubyDistribTest('linux', 'x64', 'centos6'),
-        #   RubyDistribTest('linux', 'x64', 'centos7'),
-        #   RubyDistribTest('linux', 'x64', 'fedora20'),
-        #   RubyDistribTest('linux', 'x64', 'fedora21'),
-        #   RubyDistribTest('linux', 'x64', 'fedora22'),
-        #   RubyDistribTest('linux', 'x64', 'fedora23'),
+        RubyDistribTest('linux', 'x64', 'centos6'),
+        RubyDistribTest('linux', 'x64', 'centos7'),
+        RubyDistribTest('linux', 'x64', 'fedora20'),
+        RubyDistribTest('linux', 'x64', 'fedora21'),
+        RubyDistribTest('linux', 'x64', 'fedora22'),
+        RubyDistribTest('linux', 'x64', 'fedora23'),
         RubyDistribTest('linux', 'x64', 'opensuse'),
         RubyDistribTest('linux', 'x64', 'ubuntu1204'),
         RubyDistribTest('linux', 'x64', 'ubuntu1404'),
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 3143f2c..8765f21 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -5277,6 +5277,23 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c++", 
+    "name": "bad_streaming_id_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/bad_streaming_id.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
     "name": "badreq_bad_client_test", 
     "src": [
       "test/core/bad_client/tests/badreq.cc"
@@ -5396,6 +5413,23 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c++", 
+    "name": "out_of_bounds_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/out_of_bounds.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
     "name": "server_registered_method_bad_client_test", 
     "src": [
       "test/core/bad_client/tests/server_registered_method.cc"
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 37a69a4..625d3bd 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -5935,6 +5935,32 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c++", 
+    "name": "bad_streaming_id_bad_client_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
     "name": "badreq_bad_client_test", 
     "platforms": [
       "linux", 
@@ -6117,6 +6143,32 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c++", 
+    "name": "out_of_bounds_bad_client_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
     "name": "server_registered_method_bad_client_test", 
     "platforms": [
       "linux", 
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index e550606..f11927b 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -1058,8 +1058,8 @@
 
     def test_specs(self):
         out = []
-        if self.config == 'dbg':
-            out += self.config.job_spec(
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/build_one_example.sh'],
                 timeout_seconds=10 * 60,
                 shortname='ios-buildtest-example-sample',
@@ -1067,8 +1067,9 @@
                 environ={
                     'SCHEME': 'Sample',
                     'EXAMPLE_PATH': 'src/objective-c/examples/Sample'
-                })
-            out += job_spec(
+                }))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/build_one_example.sh'],
                 timeout_seconds=10 * 60,
                 shortname='ios-buildtest-example-sample-frameworks',
@@ -1077,8 +1078,9 @@
                     'SCHEME': 'Sample',
                     'EXAMPLE_PATH': 'src/objective-c/examples/Sample',
                     'FRAMEWORKS': 'YES'
-                })
-            out += self.config.job_spec(
+                }))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/build_one_example.sh'],
                 timeout_seconds=10 * 60,
                 shortname='ios-buildtest-example-switftsample',
@@ -1086,51 +1088,58 @@
                 environ={
                     'SCHEME': 'SwiftSample',
                     'EXAMPLE_PATH': 'src/objective-c/examples/SwiftSample'
-                })
-            out += self.config.job_spec(
+                }))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/run_plugin_tests.sh'],
                 timeout_seconds=60 * 60,
                 shortname='ios-test-plugintest',
                 cpu_cost=1e6,
-                environ=_FORCE_ENVIRON_FOR_WRAPPERS)
-            out += self.config.job_spec(
+                environ=_FORCE_ENVIRON_FOR_WRAPPERS))
+        out.append(
+            self.config.job_spec(
                 ['test/core/iomgr/ios/CFStreamTests/run_tests.sh'],
                 timeout_seconds=20 * 60,
                 shortname='ios-test-cfstream-tests',
                 cpu_cost=1e6,
-                environ=_FORCE_ENVIRON_FOR_WRAPPERS)
-            out += self.config.job_spec(
+                environ=_FORCE_ENVIRON_FOR_WRAPPERS))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/run_one_test.sh'],
                 timeout_seconds=60 * 60,
                 shortname='ios-test-unittests',
                 cpu_cost=1e6,
                 environ={
-                    SCHEME: 'UnitTests'
-                })
-            out += self.config.job_spec(
+                    'SCHEME': 'UnitTests'
+                }))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/run_one_test.sh'],
                 timeout_seconds=60 * 60,
                 shortname='ios-test-interoptests',
                 cpu_cost=1e6,
                 environ={
-                    SCHEME: 'InteropTests'
-                })
-            out += self.config.job_spec(
+                    'SCHEME': 'InteropTests'
+                }))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/run_one_test.sh'],
                 timeout_seconds=60 * 60,
                 shortname='ios-test-cronettests',
                 cpu_cost=1e6,
                 environ={
-                    SCHEME: 'CronetTests'
-                })
-            out += self.config.job_spec(
+                    'SCHEME': 'CronetTests'
+                }))
+        out.append(
+            self.config.job_spec(
                 ['src/objective-c/tests/run_one_test.sh'],
                 timeout_seconds=60 * 60,
                 shortname='mac-test-basictests',
                 cpu_cost=1e6,
                 environ={
-                    SCHEME: 'MacTests'
-                })
+                    'SCHEME': 'MacTests',
+                    'PLATFORM': 'macos'
+                }))
 
         return sorted(out)
 
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 487479b..7b11d49 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -35,7 +35,7 @@
  911001cdca003337bdb93fab32740cde61bafee3 third_party/data-plane-api (heads/master)
  28f50e0fed19872e0fd50dd23ce2ee8cd759338e third_party/gflags (v2.2.0-5-g30dbc81)
  80ed4d0bbf65d57cc267dfc63bd2584557f11f9b third_party/googleapis (common-protos-1_3_1-915-g80ed4d0bb)
- ec44c6c1675c25b9827aacd08c02433cccde7780 third_party/googletest (release-1.8.0)
+ 2fe3bd994b3189899d93f1d5a881e725e046fdc2 third_party/googletest (release-1.8.1)
  6599cac0965be8e5a835ab7a5684bbef033d5ad0 third_party/libcxx (heads/release_60)
  9245d481eb3e890f708ff2d7dadf2a10c04748ba third_party/libcxxabi (heads/release_60)
  09745575a923640154bcf307fba8aedff47f240a third_party/protobuf (v3.7.0-rc.2-247-g09745575)
diff --git a/tools/run_tests/sanity/core_banned_functions.py b/tools/run_tests/sanity/core_banned_functions.py
index ce9ff0d..a9c986b 100755
--- a/tools/run_tests/sanity/core_banned_functions.py
+++ b/tools/run_tests/sanity/core_banned_functions.py
@@ -23,6 +23,7 @@
 
 # map of banned function signature to whitelist
 BANNED_EXCEPT = {
+    'grpc_slice_from_static_buffer(': ['src/core/lib/slice/slice.cc'],
     'grpc_resource_quota_ref(': ['src/core/lib/iomgr/resource_quota.cc'],
     'grpc_resource_quota_unref(':
     ['src/core/lib/iomgr/resource_quota.cc', 'src/core/lib/surface/server.cc'],