Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/sdks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ jobs:
matrix:
version: [release, devel, trunk]
os: [ubuntu-24.04, macos-13]
exclude:
- version: trunk
os: macos-13
env:
ANDROID_API_LEVEL: 24
BUNDLE_VERSION: 0.1
Expand Down Expand Up @@ -358,6 +355,9 @@ jobs:
run: |
cd swift-nio
git apply ../sdk-config/swift-nio-disable-ecn-tests.patch ../sdk-config/swift-nio-filesystem.patch
if ${{ startsWith(matrix.os, 'macos') }}; then
git apply -R ../sdk-config/swift-nio-revert.patch
fi
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_AARCH_FLAGS}
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_X_FLAGS}
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_ARM_FLAGS}
Expand Down
67 changes: 67 additions & 0 deletions swift-nio-revert.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
commit f656af6b796a9ee5e103c38cafd2346b95fdc759
Author: Johannes Weiss <[email protected]>
Date: Thu Aug 28 13:08:45 2025 +0100

SelectableEventLoop.debugDescription: fix debugDescription deadlock (#3360)

### Motivation:

In #3297, I introduced a deadlock involving `SelectableEventLoop`'s
`debugDescription`. I was under the impression that it's not possible to
call this from outside the `NIO` module so I deemed it safe. That was a
mistake :).

### Modifications:

- Make it impossible to deadlock around
`SelectableEventLoop.debugDescription`.

### Result:

- Fewer deadlocks

diff --git a/Tests/NIOPosixTests/EventLoopTest.swift b/Tests/NIOPosixTests/EventLoopTest.swift
index 65bbc653..93a5a700 100644
--- a/Tests/NIOPosixTests/EventLoopTest.swift
+++ b/Tests/NIOPosixTests/EventLoopTest.swift
@@ -2070,6 +2070,40 @@ final class EventLoopTest: XCTestCase {
XCTAssertEqual("cool", actual)
}
#endif
+
+ func testRegressionSelectableEventLoopDeadlock() throws {
+ let iterations = 1_000
+ let loop = MultiThreadedEventLoopGroup.singleton.next() as! SelectableEventLoop
+ let threadsReadySem = DispatchSemaphore(value: 0)
+ let go = DispatchSemaphore(value: 0)
+
+ let scheduleds = NIOThreadPool.singleton.runIfActive(eventLoop: loop) {
+ threadsReadySem.signal()
+ go.wait()
+ var tasks: [Scheduled<()>] = []
+ for _ in 0..<iterations {
+ tasks.append(loop.scheduleTask(in: .milliseconds(1)) {})
+ }
+ return tasks
+ }
+
+ let descriptions = NIOThreadPool.singleton.runIfActive(eventLoop: loop) {
+ threadsReadySem.signal()
+ go.wait()
+ var descriptions: [String] = []
+ for _ in 0..<iterations {
+ descriptions.append(loop.debugDescription)
+ }
+ return descriptions
+ }
+
+ threadsReadySem.wait()
+ threadsReadySem.wait()
+ go.signal()
+ go.signal()
+ XCTAssertEqual(iterations, try scheduleds.wait().map { $0.cancel() }.count)
+ XCTAssertEqual(iterations, try descriptions.wait().count)
+ }
}

private final class EventLoopWithPreSucceededFuture: EventLoop {
Loading