Merge pull request #1359 from a11r/cc2

Test client stream cancellation and fix bug exposed by the test.
diff --git a/BUILD b/BUILD
index 2a93161..79070f1 100644
--- a/BUILD
+++ b/BUILD
@@ -621,6 +621,7 @@
     "include/grpc++/generic_stub.h",
     "include/grpc++/impl/call.h",
     "include/grpc++/impl/client_unary_call.h",
+    "include/grpc++/impl/grpc_library.h",
     "include/grpc++/impl/internal_stub.h",
     "include/grpc++/impl/rpc_method.h",
     "include/grpc++/impl/rpc_service_method.h",
@@ -699,6 +700,7 @@
     "include/grpc++/generic_stub.h",
     "include/grpc++/impl/call.h",
     "include/grpc++/impl/client_unary_call.h",
+    "include/grpc++/impl/grpc_library.h",
     "include/grpc++/impl/internal_stub.h",
     "include/grpc++/impl/rpc_method.h",
     "include/grpc++/impl/rpc_service_method.h",
diff --git a/Makefile b/Makefile
index 3e7930b..8cd7160 100644
--- a/Makefile
+++ b/Makefile
@@ -3854,6 +3854,7 @@
     include/grpc++/generic_stub.h \
     include/grpc++/impl/call.h \
     include/grpc++/impl/client_unary_call.h \
+    include/grpc++/impl/grpc_library.h \
     include/grpc++/impl/internal_stub.h \
     include/grpc++/impl/rpc_method.h \
     include/grpc++/impl/rpc_service_method.h \
@@ -4117,6 +4118,7 @@
     include/grpc++/generic_stub.h \
     include/grpc++/impl/call.h \
     include/grpc++/impl/client_unary_call.h \
+    include/grpc++/impl/grpc_library.h \
     include/grpc++/impl/internal_stub.h \
     include/grpc++/impl/rpc_method.h \
     include/grpc++/impl/rpc_service_method.h \
diff --git a/build.json b/build.json
index 8838d3a..5144bb7 100644
--- a/build.json
+++ b/build.json
@@ -28,6 +28,7 @@
         "include/grpc++/generic_stub.h",
         "include/grpc++/impl/call.h",
         "include/grpc++/impl/client_unary_call.h",
+        "include/grpc++/impl/grpc_library.h",
         "include/grpc++/impl/internal_stub.h",
         "include/grpc++/impl/rpc_method.h",
         "include/grpc++/impl/rpc_service_method.h",
@@ -810,6 +811,7 @@
     },
     {
       "name": "census_statistics_multiple_writers_test",
+      "flaky": true,
       "build": "test",
       "language": "c",
       "src": [
@@ -824,6 +826,7 @@
     },
     {
       "name": "census_statistics_performance_test",
+      "flaky": true,
       "build": "test",
       "language": "c",
       "src": [
@@ -838,6 +841,7 @@
     },
     {
       "name": "census_statistics_quick_test",
+      "flaky": true,
       "build": "test",
       "language": "c",
       "src": [
diff --git a/examples/pubsub/main.cc b/examples/pubsub/main.cc
index 8f8eefa..3a40348 100644
--- a/examples/pubsub/main.cc
+++ b/examples/pubsub/main.cc
@@ -65,7 +65,6 @@
 }  // namespace
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::InitTest(&argc, &argv, true);
   gpr_log(GPR_INFO, "Start PUBSUB client");
 
@@ -146,7 +145,5 @@
 
   subscriber.Shutdown();
   publisher.Shutdown();
-  channel.reset();
-  grpc_shutdown();
   return 0;
 }
diff --git a/examples/pubsub/publisher_test.cc b/examples/pubsub/publisher_test.cc
index ac49212..6b9dcac 100644
--- a/examples/pubsub/publisher_test.cc
+++ b/examples/pubsub/publisher_test.cc
@@ -148,10 +148,8 @@
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
   gpr_log(GPR_INFO, "Start test ...");
   int result = RUN_ALL_TESTS();
-  grpc_shutdown();
   return result;
 }
diff --git a/examples/pubsub/subscriber_test.cc b/examples/pubsub/subscriber_test.cc
index 9ab60ed..b0e7fc0 100644
--- a/examples/pubsub/subscriber_test.cc
+++ b/examples/pubsub/subscriber_test.cc
@@ -147,10 +147,8 @@
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
   gpr_log(GPR_INFO, "Start test ...");
   int result = RUN_ALL_TESTS();
-  grpc_shutdown();
   return result;
 }
diff --git a/include/grpc++/completion_queue.h b/include/grpc++/completion_queue.h
index e6a8c6f..0a2a768 100644
--- a/include/grpc++/completion_queue.h
+++ b/include/grpc++/completion_queue.h
@@ -36,6 +36,7 @@
 
 #include <chrono>
 #include <grpc++/impl/client_unary_call.h>
+#include <grpc++/impl/grpc_library.h>
 #include <grpc/support/time.h>
 
 struct grpc_completion_queue;
@@ -71,11 +72,11 @@
 };
 
 // grpc_completion_queue wrapper class
-class CompletionQueue {
+class CompletionQueue : public GrpcLibrary {
  public:
   CompletionQueue();
   explicit CompletionQueue(grpc_completion_queue* take);
-  ~CompletionQueue();
+  ~CompletionQueue() GRPC_OVERRIDE;
 
   // Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT
   enum NextStatus { SHUTDOWN, GOT_EVENT, TIMEOUT };
diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h
index 2ac3eec..cbf9445 100644
--- a/include/grpc++/credentials.h
+++ b/include/grpc++/credentials.h
@@ -38,15 +38,16 @@
 #include <memory>
 
 #include <grpc++/config.h>
+#include <grpc++/impl/grpc_library.h>
 
 namespace grpc {
 class ChannelArguments;
 class ChannelInterface;
 class SecureCredentials;
 
-class Credentials {
+class Credentials : public GrpcLibrary {
  public:
-  virtual ~Credentials();
+  ~Credentials() GRPC_OVERRIDE;
 
  protected:
   friend std::unique_ptr<Credentials> CompositeCredentials(
diff --git a/include/grpc++/impl/grpc_library.h b/include/grpc++/impl/grpc_library.h
new file mode 100644
index 0000000..f9fa677
--- /dev/null
+++ b/include/grpc++/impl/grpc_library.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_IMPL_GRPC_LIBRARY_H
+#define GRPCXX_IMPL_GRPC_LIBRARY_H
+
+#include <grpc/grpc.h>
+
+namespace grpc {
+
+class GrpcLibrary {
+ public:
+  GrpcLibrary() { grpc_init(); }
+  virtual ~GrpcLibrary() { grpc_shutdown(); }
+};
+
+}  // namespace grpc
+
+
+#endif  // GRPCXX_IMPL_GRPC_LIBRARY_H
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index eb50611..0ae27e9 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -40,6 +40,7 @@
 #include <grpc++/completion_queue.h>
 #include <grpc++/config.h>
 #include <grpc++/impl/call.h>
+#include <grpc++/impl/grpc_library.h>
 #include <grpc++/impl/service_type.h>
 #include <grpc++/impl/sync.h>
 #include <grpc++/status.h>
@@ -56,7 +57,8 @@
 class ThreadPoolInterface;
 
 // Currently it only supports handling rpcs in a single thread.
-class Server GRPC_FINAL : private CallHook,
+class Server GRPC_FINAL : public GrpcLibrary,
+                          private CallHook,
                           private AsynchronousService::DispatchImpl {
  public:
   ~Server();
diff --git a/src/cpp/client/channel.h b/src/cpp/client/channel.h
index aaf4dbe..cd23924 100644
--- a/src/cpp/client/channel.h
+++ b/src/cpp/client/channel.h
@@ -38,6 +38,7 @@
 
 #include <grpc++/channel_interface.h>
 #include <grpc++/config.h>
+#include <grpc++/impl/grpc_library.h>
 
 struct grpc_channel;
 
@@ -49,7 +50,8 @@
 class Credentials;
 class StreamContextInterface;
 
-class Channel GRPC_FINAL : public ChannelInterface {
+class Channel GRPC_FINAL : public GrpcLibrary,
+                           public ChannelInterface {
  public:
   Channel(const grpc::string& target, grpc_channel* c_channel);
   ~Channel() GRPC_OVERRIDE;
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 14add60..c97a3bc 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -33,6 +33,7 @@
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 using Grpc.Core;
+using Grpc.Core.Utils;
 
 namespace Grpc.Core.Internal
 {
@@ -180,7 +181,7 @@
 
         private static void AssertCallOk(GRPCCallError callError)
         {
-            Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
+            Preconditions.CheckState(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
         }
 
         private static uint GetFlags(bool buffered)
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index a59da09..8080643 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -35,6 +35,7 @@
 using System.Collections.Concurrent;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
+using Grpc.Core.Utils;
 
 namespace Grpc.Core.Internal
 {
@@ -105,9 +106,9 @@
             grpcsharp_server_shutdown_and_notify_CALLBACK(this, callback);
         }
 
-        public GRPCCallError RequestCall(CompletionQueueSafeHandle cq, CompletionCallbackDelegate callback)
+        public void RequestCall(CompletionQueueSafeHandle cq, CompletionCallbackDelegate callback)
         {
-            return grpcsharp_server_request_call(this, cq, callback);
+            AssertCallOk(grpcsharp_server_request_call(this, cq, callback));
         }
 
         protected override bool ReleaseHandle()
@@ -115,5 +116,10 @@
             grpcsharp_server_destroy(handle);
             return true;
         }
+
+        private static void AssertCallOk(GRPCCallError callError)
+        {
+            Preconditions.CheckState(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
+        }
     }
 }
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index f086fa8..e686cdd 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -38,27 +38,29 @@
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 using Grpc.Core.Internal;
+using Grpc.Core.Utils;
 
 namespace Grpc.Core
 {
     /// <summary>
-    /// Server is implemented only to be able to do
-    /// in-process testing.
+    /// A gRPC server.
     /// </summary>
     public class Server
     {
-        // TODO: make sure the delegate doesn't get garbage collected while
+        // TODO(jtattermusch) : make sure the delegate doesn't get garbage collected while
         // native callbacks are in the completion queue.
         readonly ServerShutdownCallbackDelegate serverShutdownHandler;
         readonly CompletionCallbackDelegate newServerRpcHandler;
 
-        readonly BlockingCollection<NewRpcInfo> newRpcQueue = new BlockingCollection<NewRpcInfo>();
         readonly ServerSafeHandle handle;
+        readonly object myLock = new object();
 
         readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<string, IServerCallHandler>();
-
         readonly TaskCompletionSource<object> shutdownTcs = new TaskCompletionSource<object>();
 
+        bool startRequested;
+        bool shutdownRequested;
+
         public Server()
         {
             this.handle = ServerSafeHandle.NewServer(GetCompletionQueue(), IntPtr.Zero);
@@ -66,71 +68,81 @@
             this.serverShutdownHandler = HandleServerShutdown;
         }
 
-        // only call this before Start()
+        /// <summary>
+        /// Adds a service definition to the server. This is how you register
+        /// handlers for a service with the server.
+        /// Only call this before Start().
+        /// </summary>
         public void AddServiceDefinition(ServerServiceDefinition serviceDefinition)
         {
-            foreach (var entry in serviceDefinition.CallHandlers)
+            lock (myLock)
             {
-                callHandlers.Add(entry.Key, entry.Value);
+                Preconditions.CheckState(!startRequested);
+                foreach (var entry in serviceDefinition.CallHandlers)
+                {
+                    callHandlers.Add(entry.Key, entry.Value);
+                }
             }
         }
 
-        // only call before Start()
-        public int AddListeningPort(string addr)
-        {
-            return handle.AddListeningPort(addr);
-        }
-
-        // only call before Start()
-        public int AddListeningPort(string addr, ServerCredentials credentials)
-        {
-            using (var nativeCredentials = credentials.ToNativeCredentials())
-            {
-                return handle.AddListeningPort(addr, nativeCredentials);
-            }
-        }
-
-        public void Start()
-        {
-            handle.Start();
-
-            // TODO: this basically means the server is single threaded....
-            StartHandlingRpcs();
-        }
-
         /// <summary>
-        /// Requests and handles single RPC call.
+        /// Add a non-secure port on which server should listen.
+        /// Only call this before Start().
         /// </summary>
-        internal void RunRpc()
+        public int AddListeningPort(string addr)
         {
-            AllowOneRpc();
-
-            try
+            lock (myLock)
             {
-                var rpcInfo = newRpcQueue.Take();
-
-                // Console.WriteLine("Server received RPC " + rpcInfo.Method);
-
-                IServerCallHandler callHandler;
-                if (!callHandlers.TryGetValue(rpcInfo.Method, out callHandler))
-                {
-                    callHandler = new NoSuchMethodCallHandler();
-                }
-                callHandler.StartCall(rpcInfo.Method, rpcInfo.Call, GetCompletionQueue());
+                Preconditions.CheckState(!startRequested);
+                return handle.AddListeningPort(addr);
             }
-            catch (Exception e)
+        }
+
+        /// <summary>
+        /// Add a secure port on which server should listen.
+        /// Only call this before Start().
+        /// </summary>
+        public int AddListeningPort(string addr, ServerCredentials credentials)
+        {
+            lock (myLock)
             {
-                Console.WriteLine("Exception while handling RPC: " + e);
+                Preconditions.CheckState(!startRequested);
+                using (var nativeCredentials = credentials.ToNativeCredentials())
+                {
+                    return handle.AddListeningPort(addr, nativeCredentials);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Starts the server.
+        /// </summary>
+        public void Start()
+        {
+            lock (myLock)
+            {
+                Preconditions.CheckState(!startRequested);
+                startRequested = true;
+                
+                handle.Start();
+                AllowOneRpc();
             }
         }
 
         /// <summary>
         /// Requests server shutdown and when there are no more calls being serviced,
-        /// cleans up used resources.
+        /// cleans up used resources. The returned task finishes when shutdown procedure
+        /// is complete.
         /// </summary>
-        /// <returns>The async.</returns>
         public async Task ShutdownAsync()
         {
+            lock (myLock)
+            {
+                Preconditions.CheckState(startRequested);
+                Preconditions.CheckState(!shutdownRequested);
+                shutdownRequested = true;
+            }
+
             handle.ShutdownAndNotify(serverShutdownHandler);
             await shutdownTcs.Task;
             handle.Dispose();
@@ -152,19 +164,43 @@
             handle.Dispose();
         }
 
-        private async Task StartHandlingRpcs()
+        /// <summary>
+        /// Allows one new RPC call to be received by server.
+        /// </summary>
+        private void AllowOneRpc()
         {
-            while (true)
+            lock (myLock)
             {
-                await Task.Factory.StartNew(RunRpc);
+                if (!shutdownRequested)
+                {
+                    handle.RequestCall(GetCompletionQueue(), newServerRpcHandler);
+                }
             }
         }
 
-        private void AllowOneRpc()
+        /// <summary>
+        /// Selects corresponding handler for given call and handles the call.
+        /// </summary>
+        private void InvokeCallHandler(CallSafeHandle call, string method)
         {
-            AssertCallOk(handle.RequestCall(GetCompletionQueue(), newServerRpcHandler));
+            try
+            {
+                IServerCallHandler callHandler;
+                if (!callHandlers.TryGetValue(method, out callHandler))
+                {
+                    callHandler = new NoSuchMethodCallHandler();
+                }
+                callHandler.StartCall(method, call, GetCompletionQueue());
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine("Exception while handling RPC: " + e);
+            }
         }
 
+        /// <summary>
+        /// Handles the native callback.
+        /// </summary>
         private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr)
         {
             try
@@ -176,13 +212,16 @@
                     // TODO: handle error
                 }
 
-                var rpcInfo = new NewRpcInfo(ctx.GetServerRpcNewCall(), ctx.GetServerRpcNewMethod());
+                CallSafeHandle call = ctx.GetServerRpcNewCall();
+                string method = ctx.GetServerRpcNewMethod();
 
                 // after server shutdown, the callback returns with null call
-                if (!rpcInfo.Call.IsInvalid)
+                if (!call.IsInvalid)
                 {
-                    newRpcQueue.Add(rpcInfo);
+                    Task.Run(() => InvokeCallHandler(call, method));
                 }
+
+                AllowOneRpc();
             }
             catch (Exception e)
             {
@@ -190,6 +229,10 @@
             }
         }
 
+        /// <summary>
+        /// Handles native callback.
+        /// </summary>
+        /// <param name="eventPtr"></param>
         private void HandleServerShutdown(IntPtr eventPtr)
         {
             try
@@ -202,42 +245,9 @@
             }
         }
 
-        private static void AssertCallOk(GRPCCallError callError)
-        {
-            Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
-        }
-
         private static CompletionQueueSafeHandle GetCompletionQueue()
         {
             return GrpcEnvironment.ThreadPool.CompletionQueue;
         }
-
-        private struct NewRpcInfo
-        {
-            private CallSafeHandle call;
-            private string method;
-
-            public NewRpcInfo(CallSafeHandle call, string method)
-            {
-                this.call = call;
-                this.method = method;
-            }
-
-            public CallSafeHandle Call
-            {
-                get
-                {
-                    return this.call;
-                }
-            }
-
-            public string Method
-            {
-                get
-                {
-                    return this.method;
-                }
-            }
-        }
     }
 }
diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs
index f7429fb..abc7ef0 100644
--- a/src/csharp/Grpc.Examples.MathServer/MathServer.cs
+++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs
@@ -40,7 +40,7 @@
     {
         public static void Main(string[] args)
         {
-            String host = "0.0.0.0";
+            string host = "0.0.0.0";
 
             GrpcEnvironment.Initialize();
 
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 584bf10..6ae8041 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -80,5 +80,7 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 6da7d3c..f4ae6fa 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -607,19 +607,19 @@
     rb_raise(grpc_rb_eCallError,
              "grpc_call_start_batch failed with %s (code=%d)",
              grpc_call_error_detail_of(err), err);
-    return;
+    return Qnil;
   }
   ev = grpc_rb_completion_queue_pluck_event(cqueue, tag, timeout);
   if (ev == NULL) {
     grpc_run_batch_stack_cleanup(&st);
     rb_raise(grpc_rb_eOutOfTime, "grpc_call_start_batch timed out");
-    return;
+    return Qnil;
   }
   if (ev->data.op_complete != GRPC_OP_OK) {
     grpc_run_batch_stack_cleanup(&st);
     rb_raise(grpc_rb_eCallError, "start_batch completion failed, (code=%d)",
              ev->data.op_complete);
-    return;
+    return Qnil;
   }
 
   /* Build and return the BatchResult struct result */
diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec
index c633579..19b3e21 100755
--- a/src/ruby/grpc.gemspec
+++ b/src/ruby/grpc.gemspec
@@ -26,7 +26,7 @@
 
   s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
   s.add_dependency 'googleauth', '~> 0.4'  # reqd for interop tests
-  s.add_dependency 'logging', '~> 1.8'
+  s.add_dependency 'logging', '~> 2.0'
   s.add_dependency 'minitest', '~> 5.4'  # reqd for interop tests
 
   s.add_development_dependency 'simplecov', '~> 0.9'
diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb
index b0f6803..80b5743 100644
--- a/src/ruby/lib/grpc.rb
+++ b/src/ruby/lib/grpc.rb
@@ -30,6 +30,7 @@
 require 'grpc/errors'
 require 'grpc/grpc'
 require 'grpc/logconfig'
+require 'grpc/notifier'
 require 'grpc/version'
 require 'grpc/core/time_consts'
 require 'grpc/generic/active_call'
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index 43ba549..947c39c 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -188,7 +188,7 @@
     # @param marshalled [false, true] indicates if the object is already
     # marshalled.
     def remote_send(req, marshalled = false)
-      logger.debug("sending #{req.inspect}, marshalled? #{marshalled}")
+      logger.debug("sending #{req}, marshalled? #{marshalled}")
       if marshalled
         payload = req
       else
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index b813ab5..4ca3004 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -123,8 +123,7 @@
         break if req.equal?(END_OF_READS)
         yield req
       end
-      @loop_th.join
-      @enq_th.join
+      @enq_th.join if @enq_th.alive?
     end
 
     # during bidi-streaming, read the requests to send from a separate thread
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index 88c24aa..3375fcf 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -54,6 +54,18 @@
   end
   module_function :handle_signals
 
+  # Sets up a signal handler that adds signals to the signal handling global.
+  #
+  # Signal handlers should do as little as humanly possible.
+  # Here, they just add themselves to $grpc_signals
+  #
+  # RpcServer (and later other parts of gRPC) monitors the signals
+  # $grpc_signals in its own non-signal context.
+  def trap_signals
+    %w(INT TERM).each { |sig| trap(sig) { $grpc_signals << sig } }
+  end
+  module_function :trap_signals
+
   # Pool is a simple thread pool.
   class Pool
     # Default keep alive period is 1s
@@ -172,17 +184,6 @@
     # Signal check period is 0.25s
     SIGNAL_CHECK_PERIOD = 0.25
 
-    # Sets up a signal handler that adds signals to the signal handling global.
-    #
-    # Signal handlers should do as little as humanly possible.
-    # Here, they just add themselves to $grpc_signals
-    #
-    # RpcServer (and later other parts of gRPC) monitors the signals
-    # $grpc_signals in its own non-signal context.
-    def self.trap_signals
-      %w(INT TERM).each { |sig| trap(sig) { $grpc_signals << sig } }
-    end
-
     # setup_cq is used by #initialize to constuct a Core::CompletionQueue from
     # its arguments.
     def self.setup_cq(alt_cq)
@@ -299,12 +300,12 @@
     # Runs the server in its own thread, then waits for signal INT or TERM on
     # the current thread to terminate it.
     def run_till_terminated
-      self.class.trap_signals
+      GRPC.trap_signals
       t = Thread.new { run }
       wait_till_running
       loop do
         sleep SIGNAL_CHECK_PERIOD
-        break unless handle_signals
+        break unless GRPC.handle_signals
       end
       stop
       t.join
diff --git a/src/ruby/lib/grpc/notifier.rb b/src/ruby/lib/grpc/notifier.rb
new file mode 100644
index 0000000..caa18bb
--- /dev/null
+++ b/src/ruby/lib/grpc/notifier.rb
@@ -0,0 +1,60 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# GRPC contains the General RPC module.
+module GRPC
+  # Notifier is useful high-level synchronization primitive.
+  class Notifier
+    attr_reader :payload, :notified
+    alias_method :notified?, :notified
+
+    def initialize
+      @mutex    = Mutex.new
+      @cvar     = ConditionVariable.new
+      @notified = false
+      @payload  = nil
+    end
+
+    def wait
+      @mutex.synchronize do
+        @cvar.wait(@mutex) until notified?
+      end
+    end
+
+    def notify(payload)
+      @mutex.synchronize do
+        return Error.new('already notified') if notified?
+        @payload  = payload
+        @notified = true
+        @cvar.signal
+        return nil
+      end
+    end
+  end
+end
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index 88c6b44..98d68cc 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -29,37 +29,8 @@
 
 require 'grpc'
 
-# Notifier is useful high-level synchronization primitive.
-class Notifier
-  attr_reader :payload, :notified
-  alias_method :notified?, :notified
-
-  def initialize
-    @mutex    = Mutex.new
-    @cvar     = ConditionVariable.new
-    @notified = false
-    @payload  = nil
-  end
-
-  def wait
-    @mutex.synchronize do
-      @cvar.wait(@mutex) until notified?
-    end
-  end
-
-  def notify(payload)
-    @mutex.synchronize do
-      return Error.new('already notified') if notified?
-      @payload  = payload
-      @notified = true
-      @cvar.signal
-      return nil
-    end
-  end
-end
-
 def wakey_thread(&blk)
-  n = Notifier.new
+  n = GRPC::Notifier.new
   t = Thread.new do
     blk.call(n)
   end
diff --git a/test/core/end2end/gen_build_json.py b/test/core/end2end/gen_build_json.py
index b4a45ea..9b7db41 100755
--- a/test/core/end2end/gen_build_json.py
+++ b/test/core/end2end/gen_build_json.py
@@ -46,60 +46,60 @@
     'chttp2_socket_pair_one_byte_at_a_time': False,
 }
 
+# maps tests names to whether they run fine or not (aka, not flaky)
+END2END_TESTS = {
+    'bad_hostname': True,
+    'cancel_after_accept': False,
+    'cancel_after_accept_and_writes_closed': True,
+    'cancel_after_invoke': True,
+    'cancel_before_invoke': True,
+    'cancel_in_a_vacuum': True,
+    'census_simple_request': True,
+    'disappearing_server': True,
+    'early_server_shutdown_finishes_inflight_calls': True,
+    'early_server_shutdown_finishes_tags': True,
+    'empty_batch': True,
+    'graceful_server_shutdown': True,
+    'invoke_large_request': False,
+    'max_concurrent_streams': True,
+    'no_op': True,
+    'ping_pong_streaming': True,
+    'request_response_with_binary_metadata_and_payload': True,
+    'request_response_with_metadata_and_payload': True,
+    'request_response_with_payload': True,
+    'request_with_large_metadata': True,
+    'request_with_payload': True,
+    'simple_delayed_request': True,
+    'simple_request': True,
+    'registered_call': True,
+    'thread_stress': True,
+    'writes_done_hangs_with_pending_read': True,
 
-END2END_TESTS = [
-    'bad_hostname',
-    'cancel_after_accept',
-    'cancel_after_accept_and_writes_closed',
-    'cancel_after_invoke',
-    'cancel_before_invoke',
-    'cancel_in_a_vacuum',
-    'census_simple_request',
-    'disappearing_server',
-    'early_server_shutdown_finishes_inflight_calls',
-    'early_server_shutdown_finishes_tags',
-    'empty_batch',
-    'graceful_server_shutdown',
-    'invoke_large_request',
-    'max_concurrent_streams',
-    'no_op',
-    'ping_pong_streaming',
-    'request_response_with_binary_metadata_and_payload',
-    'request_response_with_metadata_and_payload',
-    'request_response_with_payload',
-    'request_with_large_metadata',
-    'request_with_payload',
-    'simple_delayed_request',
-    'simple_request',
-    'registered_call',
-    'thread_stress',
-    'writes_done_hangs_with_pending_read',
-
-    'cancel_after_accept_legacy',
-    'cancel_after_accept_and_writes_closed_legacy',
-    'cancel_after_invoke_legacy',
-    'cancel_before_invoke_legacy',
-    'cancel_in_a_vacuum_legacy',
-    'census_simple_request_legacy',
-    'disappearing_server_legacy',
-    'early_server_shutdown_finishes_inflight_calls_legacy',
-    'early_server_shutdown_finishes_tags_legacy',
-    'graceful_server_shutdown_legacy',
-    'invoke_large_request_legacy',
-    'max_concurrent_streams_legacy',
-    'no_op_legacy',
-    'ping_pong_streaming_legacy',
-    'request_response_with_binary_metadata_and_payload_legacy',
-    'request_response_with_metadata_and_payload_legacy',
-    'request_response_with_payload_legacy',
-    'request_response_with_trailing_metadata_and_payload_legacy',
-    'request_with_large_metadata_legacy',
-    'request_with_payload_legacy',
-    'simple_delayed_request_legacy',
-    'simple_request_legacy',
-    'thread_stress_legacy',
-    'writes_done_hangs_with_pending_read_legacy',
-]
+    'cancel_after_accept_legacy': False,
+    'cancel_after_accept_and_writes_closed_legacy': True,
+    'cancel_after_invoke_legacy': True,
+    'cancel_before_invoke_legacy': True,
+    'cancel_in_a_vacuum_legacy': True,
+    'census_simple_request_legacy': True,
+    'disappearing_server_legacy': True,
+    'early_server_shutdown_finishes_inflight_calls_legacy': True,
+    'early_server_shutdown_finishes_tags_legacy': True,
+    'graceful_server_shutdown_legacy': True,
+    'invoke_large_request_legacy': False,
+    'max_concurrent_streams_legacy': True,
+    'no_op_legacy': True,
+    'ping_pong_streaming_legacy': True,
+    'request_response_with_binary_metadata_and_payload_legacy': True,
+    'request_response_with_metadata_and_payload_legacy': True,
+    'request_response_with_payload_legacy': True,
+    'request_response_with_trailing_metadata_and_payload_legacy': True,
+    'request_with_large_metadata_legacy': True,
+    'request_with_payload_legacy': True,
+    'simple_delayed_request_legacy': True,
+    'simple_request_legacy': True,
+    'thread_stress_legacy': True,
+    'writes_done_hangs_with_pending_read_legacy': True,
+}
 
 
 def main():
@@ -122,7 +122,7 @@
               'src': ['test/core/end2end/tests/%s.c' % t],
               'headers': ['test/core/end2end/tests/cancel_test_helpers.h']
           }
-          for t in sorted(END2END_TESTS)] + [
+          for t in sorted(END2END_TESTS.keys())] + [
           {
               'name': 'end2end_certs',
               'build': 'private',
@@ -140,7 +140,7 @@
               'build': 'test',
               'language': 'c',
               'src': [],
-              'flaky': 'invoke_large_request' in t,
+              'flaky': not END2END_TESTS[t],
               'deps': [
                   'end2end_fixture_%s' % f,
                   'end2end_test_%s' % t,
@@ -152,7 +152,7 @@
               ]
           }
       for f in sorted(END2END_FIXTURES.keys())
-      for t in sorted(END2END_TESTS)] + [
+      for t in sorted(END2END_TESTS.keys())] + [
           {
               'name': '%s_%s_unsecure_test' % (f, t),
               'build': 'test',
@@ -170,7 +170,7 @@
               ]
           }
       for f in sorted(END2END_FIXTURES.keys()) if not END2END_FIXTURES[f]
-      for t in sorted(END2END_TESTS)]}
+      for t in sorted(END2END_TESTS.keys())]}
   print simplejson.dumps(json, sort_keys=True, indent=2 * ' ')
 
 
diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc
index 24251f2..883f1dc 100644
--- a/test/cpp/client/credentials_test.cc
+++ b/test/cpp/client/credentials_test.cc
@@ -56,8 +56,6 @@
 
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
-  grpc_init();
   int ret = RUN_ALL_TESTS();
-  grpc_shutdown();
   return ret;
 }
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index dd294d9..e3cbfd6 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -595,9 +595,6 @@
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
-  int result = RUN_ALL_TESTS();
-  grpc_shutdown();
-  return result;
+  return RUN_ALL_TESTS();
 }
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 48174ec..dd26552 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -583,9 +583,6 @@
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
-  int result = RUN_ALL_TESTS();
-  grpc_shutdown();
-  return result;
+  return RUN_ALL_TESTS();
 }
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 584d4bc..e70a1cb 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -280,9 +280,6 @@
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
-  int result = RUN_ALL_TESTS();
-  grpc_shutdown();
-  return result;
+  return RUN_ALL_TESTS();
 }
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 42d16f2..072968f 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -76,8 +76,6 @@
 using grpc::testing::GetServiceAccountJsonKey;
 
 int main(int argc, char** argv) {
-  grpc_init();
-
   grpc::testing::InitTest(&argc, &argv, true);
 
   int ret = 0;
@@ -129,8 +127,6 @@
         FLAGS_test_case.c_str());
     ret = 1;
   }
-  client.Reset(nullptr);
 
-  grpc_shutdown();
   return ret;
 }
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 7888102..22b8910 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -218,13 +218,11 @@
 static void sigint_handler(int x) { got_sigint = true; }
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::InitTest(&argc, &argv, true);
   signal(SIGINT, sigint_handler);
 
   GPR_ASSERT(FLAGS_port != 0);
   RunServer();
 
-  grpc_shutdown();
   return 0;
 }
diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc
index 0669ccf..93b1247 100644
--- a/test/cpp/qps/qps_driver.cc
+++ b/test/cpp/qps/qps_driver.cc
@@ -69,7 +69,6 @@
 using grpc::testing::ResourceUsage;
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::InitTest(&argc, &argv, true);
 
   RpcType rpc_type;
@@ -104,6 +103,5 @@
   ReportLatency(result);
   ReportTimes(result);
 
-  grpc_shutdown();
   return 0;
 }
diff --git a/test/cpp/qps/smoke_test.cc b/test/cpp/qps/smoke_test.cc
index 9531913..e390730 100644
--- a/test/cpp/qps/smoke_test.cc
+++ b/test/cpp/qps/smoke_test.cc
@@ -136,14 +136,11 @@
 }  // namespace grpc
 
 int main(int argc, char** argv) {
-  grpc_init();
-
   using namespace grpc::testing;
   RunSynchronousStreamingPingPong();
   RunSynchronousUnaryPingPong();
   RunAsyncUnaryPingPong();
   RunQPS();
 
-  grpc_shutdown();
   return 0;
 }
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index 896a85c..281c617 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -64,13 +64,11 @@
 }  // namespace grpc
 
 int main(int argc, char** argv) {
-  grpc_init();
   grpc::testing::InitTest(&argc, &argv, true);
 
   signal(SIGINT, sigint_handler);
 
   grpc::testing::RunServer();
-
-  grpc_shutdown();
+  
   return 0;
 }
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 32ef392..457a5e7 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -123,9 +123,6 @@
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
-  grpc_init();
   ::testing::InitGoogleTest(&argc, argv);
-  int result = RUN_ALL_TESTS();
-  grpc_shutdown();
-  return result;
+  return RUN_ALL_TESTS();
 }
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index ee9f275..d71a7a0 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -79,8 +79,6 @@
               "Path to output file to write serialized response.");
 
 int main(int argc, char** argv) {
-  grpc_init();
-
   grpc::testing::InitTest(&argc, &argv, true);
 
   if (argc < 4 || grpc::string(argv[1]) != "call") {
@@ -127,7 +125,5 @@
     output_file << response;
   }
 
-  channel.reset();
-  grpc_shutdown();
   return 0;
 }
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index ad994e9..68b22d7 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -65,7 +65,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "census_statistics_multiple_writers_test", 
     "platforms": [
@@ -74,7 +74,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "census_statistics_performance_test", 
     "platforms": [
@@ -83,7 +83,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "census_statistics_quick_test", 
     "platforms": [
@@ -703,7 +703,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_fake_security_cancel_after_accept_test", 
     "platforms": [
@@ -730,7 +730,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_fake_security_cancel_after_accept_legacy_test", 
     "platforms": [
@@ -1153,7 +1153,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_fullstack_cancel_after_accept_test", 
     "platforms": [
@@ -1180,7 +1180,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_fullstack_cancel_after_accept_legacy_test", 
     "platforms": [
@@ -1603,7 +1603,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_fullstack_uds_cancel_after_accept_test", 
     "platforms": [
@@ -1630,7 +1630,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_fullstack_uds_cancel_after_accept_legacy_test", 
     "platforms": [
@@ -2053,7 +2053,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_simple_ssl_fullstack_cancel_after_accept_test", 
     "platforms": [
@@ -2080,7 +2080,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test", 
     "platforms": [
@@ -2503,7 +2503,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test", 
     "platforms": [
@@ -2530,7 +2530,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test", 
     "platforms": [
@@ -2953,7 +2953,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_socket_pair_cancel_after_accept_test", 
     "platforms": [
@@ -2980,7 +2980,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_socket_pair_cancel_after_accept_legacy_test", 
     "platforms": [
@@ -3403,7 +3403,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test", 
     "platforms": [
@@ -3430,7 +3430,7 @@
     ]
   }, 
   {
-    "flaky": false, 
+    "flaky": true, 
     "language": "c", 
     "name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test", 
     "platforms": [
diff --git a/vsprojects/grpc++/grpc++.vcxproj b/vsprojects/grpc++/grpc++.vcxproj
index 38eca1a..07c018f 100644
--- a/vsprojects/grpc++/grpc++.vcxproj
+++ b/vsprojects/grpc++/grpc++.vcxproj
@@ -96,6 +96,7 @@
     <ClInclude Include="..\..\include\grpc++\generic_stub.h" />
     <ClInclude Include="..\..\include\grpc++\impl\call.h" />
     <ClInclude Include="..\..\include\grpc++\impl\client_unary_call.h" />
+    <ClInclude Include="..\..\include\grpc++\impl\grpc_library.h" />
     <ClInclude Include="..\..\include\grpc++\impl\internal_stub.h" />
     <ClInclude Include="..\..\include\grpc++\impl\rpc_method.h" />
     <ClInclude Include="..\..\include\grpc++\impl\rpc_service_method.h" />
diff --git a/vsprojects/grpc++/grpc++.vcxproj.filters b/vsprojects/grpc++/grpc++.vcxproj.filters
index 6466a0f..46b33bb 100644
--- a/vsprojects/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/grpc++/grpc++.vcxproj.filters
@@ -120,6 +120,9 @@
     <ClInclude Include="..\..\include\grpc++\impl\client_unary_call.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\impl\grpc_library.h">
+      <Filter>include\grpc++\impl</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\impl\internal_stub.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>