fix: clear pending pings to avoid promise leaks on connection close/suspend
- Add cancel() method to RttCommand to fail promise on connection close - Add dequeueAll() method to ConcurrentQueue for batch cleanup - Call clearPendingPings() in close(), suspend(), and disconnect() methods - Prevents 'leaking promise' crash when connection is closed while pings are pending
This commit is contained in:
@@ -712,6 +712,7 @@ class ConnectionHandler: ChannelInboundHandler {
|
||||
guard let eventLoop = self.channel?.eventLoop else {
|
||||
self.state.withLockedValue { $0 = .closed }
|
||||
self.pingTask?.cancel()
|
||||
clearPendingPings() // Clear pending pings to avoid promise leaks
|
||||
self.fire(.closed)
|
||||
return
|
||||
}
|
||||
@@ -720,6 +721,7 @@ class ConnectionHandler: ChannelInboundHandler {
|
||||
eventLoop.execute {
|
||||
self.state.withLockedValue { $0 = .closed }
|
||||
self.pingTask?.cancel()
|
||||
self.clearPendingPings() // Clear pending pings to avoid promise leaks
|
||||
self.channel?.close(mode: .all, promise: promise)
|
||||
}
|
||||
|
||||
@@ -735,8 +737,20 @@ class ConnectionHandler: ChannelInboundHandler {
|
||||
|
||||
private func disconnect() async throws {
|
||||
self.pingTask?.cancel()
|
||||
clearPendingPings() // Clear pending pings to avoid promise leaks
|
||||
try await self.channel?.close().get()
|
||||
}
|
||||
|
||||
/// Clear all pending ping requests to avoid promise leaks
|
||||
private func clearPendingPings() {
|
||||
let pendingPings = pingQueue.dequeueAll()
|
||||
for ping in pendingPings {
|
||||
ping.cancel()
|
||||
}
|
||||
if !pendingPings.isEmpty {
|
||||
logger.debug("Cleared \(pendingPings.count) pending ping(s)")
|
||||
}
|
||||
}
|
||||
|
||||
func suspend() async throws {
|
||||
self.reconnectTask?.cancel()
|
||||
@@ -746,6 +760,7 @@ class ConnectionHandler: ChannelInboundHandler {
|
||||
guard let eventLoop = self.channel?.eventLoop else {
|
||||
// Set state to suspended even if channel is nil
|
||||
self.state.withLockedValue { $0 = .suspended }
|
||||
clearPendingPings() // Clear pending pings to avoid promise leaks
|
||||
return
|
||||
}
|
||||
let promise = eventLoop.makePromise(of: Void.self)
|
||||
@@ -759,8 +774,10 @@ class ConnectionHandler: ChannelInboundHandler {
|
||||
|
||||
if shouldClose {
|
||||
self.pingTask?.cancel()
|
||||
self.clearPendingPings() // Clear pending pings to avoid promise leaks
|
||||
self.channel?.close(mode: .all, promise: promise)
|
||||
} else {
|
||||
self.clearPendingPings() // Clear pending pings even if not closing
|
||||
promise.succeed()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user