【发布时间】:2022-02-10 21:26:38
【问题描述】:
我在一些使用 Swift 新并发特性的代码中偶尔会遇到崩溃。这种崩溃似乎从未发生在开发版本上,无论是在模拟器中还是当我直接从 Xcode 在设备上安装代码时。然而,当人们从 TestFlight 安装代码时,这种情况经常发生。
实际的崩溃是这样的:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000040
Exception Codes: 0x0000000000000001, 0x0000000000000040
Thread 6 name:
Thread 6 Crashed:
0 libswift_Concurrency.dylib 0x00000001e6df7440 swift::TaskGroup::offer(swift::AsyncTask*, swift::AsyncContext*) + 504 (TaskGroup.cpp:603)
1 libswift_Concurrency.dylib 0x00000001e6df3c5c swift::AsyncTask::completeFuture(swift::AsyncContext*) + 132 (Task.cpp:180)
2 libswift_Concurrency.dylib 0x00000001e6df54d0 completeTaskAndRelease(swift::AsyncContext*, swift::SwiftError*) + 128 (Task.cpp:323)
3 libswift_Concurrency.dylib 0x00000001e6df5425 completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) + 1 (Task.cpp:365)
我不确定这与哪一行代码相对应,但很可能在这里的某个地方:
class MyClass {
var results: [String: Set<String>] = [:]
func getSingleResult(index: Int) async -> (String, Set<String>) {
// ....
}
func getAllResults(range: ClosedRange<Int>) async -> [String: Set<String>] {
await withTaskGroup(
of: (String, Set<String>).self,
returning: [String: Set<String>].self
) { [self] group in
for i in range {
group.addTask { await getSingleResult(index: i) }
}
var results: [String: Set<String>] = [:]
for await result in group {
results[result.0] = result.1
}
return results
}
}
func blockingDoWork(range: ClosedRange<Int>) {
results = [:]
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
Task.init {
results = await getAllResults(range: range)
dispatchGroup.leave()
}
dispatchGroup.wait()
// Now do something with `results`
}
我试图弥合同步代码和异步代码之间的鸿沟(可能是错误的方式)。基本上我有一个单线程/同步代码,然后创建可变数量的异步调用并尝试阻塞,直到所有这些调用完成。它将这些调用的结果汇总到 results 类成员中,这可能不是最好的方法,但却是我可以让异步代码与同步代码进行通信的唯一方法。
此代码在开发版本中似乎运行良好,在发布版本中运行了 1000 次,但随后崩溃。
我似乎无法打开线程清理器或地址清理器,因为我的 Xcode 项目使用 Swift 包管理器,并且在使用这两者时存在导致构建失败的错误。
有什么想法可能会出错吗?我假设我对开发构建很幸运,并且我在这段代码中遇到了一些基本问题,但我对 Swift 新并发功能的微妙之处了解不足,无法识别它。
【问题讨论】:
标签: swift async-await