Эх сурвалжийг харах

Close request writer when finishing with an error (#98)

As part of the investigation for
https://github.com/grpc/grpc-swift-nio-transport/issues/95, we realised
that the request writer would never be finished if an exception was
thrown inside the writing closure. This PR adds a test reproducing this
and makes sure the writer is properly finished.
Gus Cairo 6 сар өмнө
parent
commit
bb97afef4b

+ 3 - 0
Sources/GRPCNIOTransportCore/Client/Connection/Connection.swift

@@ -447,6 +447,9 @@ extension Connection {
       package func finish(throwing error: any Error) {
         // Fire the error inbound; this fails the inbound writer.
         self.http2Stream.channel.pipeline.fireErrorCaught(error)
+
+        // Now finish the request writer, to signal we're done writing.
+        self.requestWriter.finish()
       }
     }
 

+ 20 - 0
Tests/GRPCNIOTransportHTTP2Tests/HTTP2TransportTests.swift

@@ -1674,6 +1674,26 @@ final class HTTP2TransportTests: XCTestCase {
       XCTAssertNotNil(peerInfo.client.local.wholeMatch(of: /unix:peer-info-uds/))
     }
   }
+
+  enum TestError: Error {
+    case someError
+  }
+
+  func testThrowingInClientStreamWriter() async throws {
+    try await forEachTransportPair { client, server, transport in
+      do {
+        _ = try await client.clientStream(
+          request: .init(producer: { writer in
+            throw TestError.someError
+          })
+        )
+        XCTFail("Test should have failed")
+      } catch let error as RPCError {
+        XCTAssertEqual(error.code, .unavailable)
+        XCTAssertEqual(error.message, "Stream unexpectedly closed with error.")
+      }
+    }
+  }
 }
 
 extension [HTTP2TransportTests.Transport] {