From a00698fc444230ef4b0c8a787d4579ea5f0a5f17 Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Mon, 17 Oct 2016 14:53:48 +0200
Subject: [PATCH] allow new RPC once previous call has been handled

---
 src/csharp/Grpc.Core/Server.cs | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index dd4a405ed92..a11f1a88461 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -310,7 +310,7 @@ namespace Grpc.Core
         /// <summary>
         /// Selects corresponding handler for given call and handles the call.
         /// </summary>
-        private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
+        private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq, Action continuation)
         {
             try
             {
@@ -325,6 +325,11 @@ namespace Grpc.Core
             {
                 Logger.Warning(e, "Exception while handling RPC.");
             }
+
+            if (continuation != null)
+            {
+                continuation();
+            }
         }
 
         /// <summary>
@@ -332,8 +337,7 @@ namespace Grpc.Core
         /// </summary>
         private void HandleNewServerRpc(bool success, BatchContextSafeHandle ctx, CompletionQueueSafeHandle cq)
         {
-			Task.Run(() => AllowOneRpc(cq));
-
+            bool nextRpcRequested = false;
             if (success)
             {
                 ServerRpcNew newRpc = ctx.GetServerRpcNew(this);
@@ -341,9 +345,21 @@ namespace Grpc.Core
                 // after server shutdown, the callback returns with null call
                 if (!newRpc.Call.IsInvalid)
                 {
-                    HandleCallAsync(newRpc, cq);  // we don't need to await.
+                    nextRpcRequested = true;
+
+                    // Start asynchronous handler for the call.
+                    // Don't await, the continuations will run on gRPC thread pool once triggered
+                    // by cq.Next().
+                    #pragma warning disable 4014
+                    HandleCallAsync(newRpc, cq, () => AllowOneRpc(cq));
+                    #pragma warning restore 4014
                 }
             }
+
+            if (!nextRpcRequested)
+            {
+                AllowOneRpc(cq);
+            }
         }
 
         /// <summary>