From b1b99809d412479ee20a4ad9c1d367fd7d0ce242 Mon Sep 17 00:00:00 2001 From: Michael Gathara Date: Wed, 17 Dec 2025 20:58:50 -0600 Subject: [PATCH] Fix: Kubes Cluster in Container Crashing Container (IS#923) (#930) - Fixes issue #923 - I fixed a race condition in `ConnectHandler.swift` where an asynchronous network connection could complete after the handler had already been removed from the pipeline. - This prevents the EXC_BREAKPOINT crash in container-runtime-linux that occurred when kinc (Kubernetes in Container) created rapid connections. - The actual fix was inadvertently applied in #957, so this PR contains only the test code. --- .../ConnectHandlerRaceTest.swift | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Tests/SocketForwarderTests/ConnectHandlerRaceTest.swift diff --git a/Tests/SocketForwarderTests/ConnectHandlerRaceTest.swift b/Tests/SocketForwarderTests/ConnectHandlerRaceTest.swift new file mode 100644 index 00000000..1a1c314d --- /dev/null +++ b/Tests/SocketForwarderTests/ConnectHandlerRaceTest.swift @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// Copyright © 2025 Apple Inc. and the container project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//===----------------------------------------------------------------------===// + +import NIO +import Testing + +@testable import SocketForwarder + +struct ConnectHandlerRaceTest { + let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) + + @Test + func testRapidConnectDisconnect() async throws { + let requestCount = 500 + + let serverAddress = try SocketAddress(ipAddress: "127.0.0.1", port: 0) + let server = TCPEchoServer(serverAddress: serverAddress, eventLoopGroup: eventLoopGroup) + let serverChannel = try await server.run().get() + let actualServerAddress = try #require(serverChannel.localAddress) + + let proxyAddress = try SocketAddress(ipAddress: "127.0.0.1", port: 0) + let forwarder = try TCPForwarder( + proxyAddress: proxyAddress, + serverAddress: actualServerAddress, + eventLoopGroup: eventLoopGroup + ) + let forwarderResult = try await forwarder.run().get() + let actualProxyAddress = try #require(forwarderResult.proxyAddress) + + try await withThrowingTaskGroup(of: Void.self) { group in + for _ in 0..