Skip to content

Commit 423fd0b

Browse files
authored
Fix crash if connection is closed very early (#671)
* Fix crash if connection is closed very early If the channel is closed before flatMap is executed, all ChannelHandler are removed and `TLSEventsHandler` is therefore not present either. We need to tolerate this even though it is very rare. Testing ideas welcome. Fixes #670 * drop precondition to assert
1 parent 864c8d9 commit 423fd0b

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

Sources/AsyncHTTPClient/ConnectionPool/HTTPConnectionPool+Factory.swift

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,14 +361,19 @@ extension HTTPConnectionPool.ConnectionFactory {
361361
var channelFuture = bootstrapFuture.flatMap { bootstrap -> EventLoopFuture<Channel> in
362362
return bootstrap.connect(target: self.key.connectionTarget)
363363
}.flatMap { channel -> EventLoopFuture<(Channel, String?)> in
364-
// It is save to use `try!` here, since we are sure, that a `TLSEventsHandler` exists
365-
// within the pipeline. It is added in `makeTLSBootstrap`.
366-
let tlsEventHandler = try! channel.pipeline.syncOperations.handler(type: TLSEventsHandler.self)
367-
368-
// The tlsEstablishedFuture is set as soon as the TLSEventsHandler is in a
369-
// pipeline. It is created in TLSEventsHandler's handlerAdded method.
370-
return tlsEventHandler.tlsEstablishedFuture!.flatMap { negotiated in
371-
channel.pipeline.removeHandler(tlsEventHandler).map { (channel, negotiated) }
364+
do {
365+
// if the channel is closed before flatMap is executed, all ChannelHandler are removed
366+
// and TLSEventsHandler is therefore not present either
367+
let tlsEventHandler = try channel.pipeline.syncOperations.handler(type: TLSEventsHandler.self)
368+
369+
// The tlsEstablishedFuture is set as soon as the TLSEventsHandler is in a
370+
// pipeline. It is created in TLSEventsHandler's handlerAdded method.
371+
return tlsEventHandler.tlsEstablishedFuture!.flatMap { negotiated in
372+
channel.pipeline.removeHandler(tlsEventHandler).map { (channel, negotiated) }
373+
}
374+
} catch {
375+
assert(channel.isActive == false, "if the channel is still active then TLSEventsHandler must be present but got error \(error)")
376+
return channel.eventLoop.makeFailedFuture(HTTPClientError.remoteConnectionClosed)
372377
}
373378
}
374379

0 commit comments

Comments
 (0)