I’m seeing a crash relating to TaskGroup, but unfortunately it’s only coming up in production and I have limited information on it (via Crashlytics). I’m guessing I’m abusing TaskGroup one way or another. Any advice as to where to start investigating an issue like this? Here’s the offending thread. I’ve tried at length to reproduce it locally but no luck.
I have only one use of TaskGroup in my project, and it seems pretty trivial.
// Function that processes a bunch of 'action triggers' and produces a stream of actions
func run(action: Action, find: @escaping (Model.Type) -> Model?) -> AsyncStream<Action> {
AsyncStream { continuation in
Task {
await withTaskGroup(of: Void.self) { group in
for trigger in triggers {
group.addTask {
for await result in trigger(action, find) {
if result is VoidAction { continue }
continuation.yield(result)
}
}
}
await group.waitForAll()
continuation.finish()
}
}
}
}
// Later, from an async context. Process an action and dispatch its output.
Task {
for await output in run(action: action, find: { store.find($0) }) {
try await store.dispatch(output)
}
}
Is there any way to dig into this without a more complete crash report?
Thanks for sharing your code. Hopefully someone more knowledgable than myself can reply. I was hitting a similar (but not the same) problem where my store.dispatch contained some Core Data related code that was not following proper managed object thread containment rules. (It mostly worked, except for sometimes. )
A random thought I had. Is it okay for the different async child tasks to use the continuation variable concurrently? IOW, is continuation.yield re-enterant?
I eventually narrowed this down to iOS 15.3, and older (iPhone 6s, 7, 8, X) devices. It seems to be fixed on iOS 15.4. I also fixed it by marking the two inner closures (withTaskGroup, addTask) @MainActor.
I've also seen this crash. I can confirm it is reproducible on versions prior to 15.4 which is a blocker for adopting structured concurrency at my company.
I had hope Swift 5.6 would fix this issue. It seemingly did but a library responsible for the crash was for some reason not updated in Xcode 13.3 toolchain.
💣 Program crashed: Bus error at 0x0005000200020062
Thread 0 crashed:
0 0x0000ffff8367aadc swift_task_cancel + 28 in libswift_Concurrency.so
1 0x0000ffff8367b508 swift_taskGroup_cancelAll + 47 in libswift_Concurrency.so
2 InfernoDevice.shutdown() + 551 in infernod at /build/inferno/control/InfernoAES70/Sources/InfernoDevice/Device.swift:490:27
488│
489│ if let ocp1TaskGroup {
490│ ocp1TaskGroup.cancelAll()
│ ▲
491│ }
492│
Please file a bug with details about versions and best if able to provide a reproducer. It’s not so easy to follow up on such without context code snippet.