Skip to content

Commit 64657c7

Browse files
glbrnttWendellXY
authored andcommitted
Connect EmbeddedChannel when FuzzTesting (grpc#1569)
Motivation: FuzzTesting uses EmbeddedChannel but never called connect meaning that channel active was never fired. HTTP/2 recently added activity state checking and complains that we fire inactive without having activated. Modifications: - call connect on the EmbeddedChannel in fuzzing and in tests - if the connection manager is closed while connecting it waits for the connect to resolve before closing the channel, however the channel future is completed before channel active is fired so defer closing it until the next loop tick. Result: Channel active is more frequently fired at the right time.
1 parent 560d66f commit 64657c7

File tree

3 files changed

+11
-3
lines changed

3 files changed

+11
-3
lines changed

FuzzTesting/Sources/ServerFuzzerLib/ServerFuzzer.swift

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public func test(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
2222
let bytes = UnsafeRawBufferPointer(start: start, count: count)
2323

2424
let channel = EmbeddedChannel()
25+
try! channel.connect(to: try! SocketAddress(ipAddress: "127.0.0.1", port: 0)).wait()
26+
2527
defer {
2628
_ = try? channel.finish()
2729
}

Sources/GRPC/ConnectionManager.swift

+8-3
Original file line numberDiff line numberDiff line change
@@ -514,9 +514,14 @@ internal final class ConnectionManager {
514514
state.candidate.whenComplete {
515515
switch $0 {
516516
case let .success(channel):
517-
// In case we do successfully connect, close immediately.
518-
channel.close(mode: .all, promise: nil)
519-
promise.completeWith(channel.closeFuture.recoveringFromUncleanShutdown())
517+
// In case we do successfully connect, close on the next loop tick. When connecting a
518+
// channel NIO will complete the promise for the channel before firing channel active.
519+
// That means we may close and fire inactive before active which HTTP/2 will be unhappy
520+
// about.
521+
self.eventLoop.execute {
522+
channel.close(mode: .all, promise: nil)
523+
promise.completeWith(channel.closeFuture.recoveringFromUncleanShutdown())
524+
}
520525

521526
case .failure:
522527
// We failed to connect, that's fine we still shutdown successfully.

Tests/GRPCTests/ServerFuzzingRegressionTests.swift

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ final class ServerFuzzingRegressionTests: GRPCTestCase {
3131

3232
private func runTest(withInput buffer: ByteBuffer) {
3333
let channel = EmbeddedChannel()
34+
try! channel.connect(to: try! SocketAddress(ipAddress: "127.0.0.1", port: 0)).wait()
3435
defer {
3536
_ = try? channel.finish()
3637
}

0 commit comments

Comments
 (0)