Thank you for your diligence on this issue Quinn!
Post
Replies
Boosts
Views
Activity
I tried with a brand new user as you asked and it reproduces in that environment as well.
Also, for the record, we do see this bug on M3 machines with our production code-base. Since the bug has to do with the file structure of the package, and with the code in at least 2 source files, I don't know what the file structure needs to be to reproduce on an M3. I wasn't aware this was processor-specific when I was tearing our project apart looking for the trigger.
Hopefully fixing this bug with the reproducible case on an M1 will also fix it for all cases.
No, I didn't try that because with the latest project I sent I have 5 other machines on our team that can reproduce the issue. The common factor seems to be some version of the M1 chip. We have 4-5 people with M3 that cannot reproduce and one person with an M2 that cannot reproduce.
Found a reproducible case that works on about half of our machines. Updated the FB15511118 with the project.
FB15511118
I have a reproducible project. I zipped it up but I can't seem to attach a zip file. It's only 91KB
Crash report attached.
xctest-2024-10-09-091718.txt
I’d like to confirm two things:
You’re testing this from Xcode 16.0.
Targeting the iOS 18.0 simulator.
Yes on both.
First, add this your code:
The Test.counter line generates this error:
Main actor-isolated static property 'counter' can not be mutated from a nonisolated context
Second, tweak your setup like this:
progress.cancellationHandler = { @Sendable in }
Unfortunately, that does not prevent the trap, no.
Thanks for your help.
Interestingly enough, I just ran our test against Mac Catalyst and it doesn't crash, but I get a purple runtime warning:
warning: data race detected: @MainActor function at MyController.swift:8 was not called on the main thread
Within our production codebase, I can reproduce with this simple class:
public final class MyController {
public let progress: Progress
init() {
progress = Progress()
progress.cancellationHandler = {}
}
}
And this simple test:
import Testing
@Test
func reproDispatchAssertQueueFail() async throws {
let dc = MyController()
dc.progress.cancel()
}
In this case, MyController is defined in a Package, which the test imports. I cannot reproduce this when MyController is defined in the same file as the test.
Pulling that same code into a brand new sample project, I cannot reproduce this.
Also, I do not see this issue when testing against iOS 17.5, I'm only seeing it on iOS 18 simulators.
Also, it readily reproduces after running the test immediately after a clean and rebuild of the package defining MyController.
I've got the same basic project that I extracted to try to get a reproducer. I also setup unit tests with both Swift Testing and XCTest (we mostly see this issue in our test environment). Unfortunately, I have not been able to reproduce it outside of our codebase.
Our code is in a Swift Package, so one thing that I haven't tried is breaking out this reproducible code into a package and making that package a dependency of an app. There is no practical difference I can identify between the code we have tried to reproduce the crash and our production code.
MyController is a simple class not bound to any actor. The init code is above, it is also not bound to any actor.
I tried binding the init to the MainActor, that didn't help.
I also tried making the closures passed into progress @Sendable and that did not fix it, which surprised me.
Thanks Quinn. I can also work around the bug by using for in instead of .forEach:
...
init(store: MyStore) async throws {
for persisted in try await store.persisted {
credentials.append(persisted)
}
}
So I think it has something to do with Actor inference in the .forEach closure.
I filed a bug with Swift: https://github.com/swiftlang/swift/issues/76804
I no longer have a need for this. I misunderstood the worldAlignment property. Now that I understand it, I don't need this specific question answered