浏览代码

Delay closing until the next loop tick (#1326)

Motivation:

When the idle handler determines that the channel needs to be closed
(becuase the connection is no longer required) it does so on the current
event loop tick. Closing immediately means that some events which are
already scheduled to run on the current tick may be dropped unexpectedly.

Modifications:

- Execute the channel close on the next event-loop tick.
- Fixup a test which now requires an extra loop `run()`.

Result:

Shutdown is a little more graceful.
George Barnett 4 年之前
父节点
当前提交
c43be58103
共有 2 个文件被更改,包括 7 次插入2 次删除
  1. 6 2
      Sources/GRPC/GRPCIdleHandler.swift
  2. 1 0
      Tests/GRPCTests/ConnectionManagerTests.swift

+ 6 - 2
Sources/GRPC/GRPCIdleHandler.swift

@@ -157,8 +157,12 @@ internal final class GRPCIdleHandler: ChannelInboundHandler {
     }
 
     // Close the channel, if necessary.
-    if operations.shouldCloseChannel {
-      self.context?.close(mode: .all, promise: nil)
+    if operations.shouldCloseChannel, let context = self.context {
+      // Close on the next event-loop tick so we don't drop any events which are
+      // currently being processed.
+      context.eventLoop.execute {
+        context.close(mode: .all, promise: nil)
+      }
     }
   }
 

+ 1 - 0
Tests/GRPCTests/ConnectionManagerTests.swift

@@ -800,6 +800,7 @@ extension ConnectionManagerTests {
         payload: .goAway(lastStreamID: 1, errorCode: .noError, opaqueData: nil)
       )
       XCTAssertNoThrow(try channel.writeInbound(goAway))
+      self.loop.run()
     }
 
     self.loop.run()