1

我在 iOS 上有一些生产崩溃,如下所示:

Crashed: com.superdupertango.Server.CallbackRunQueue
0  SDTServer                      0x102b78ed0 specialized Dictionary.subscript.getter + 4378562256 (<compiler-generated>:4378562256)
1  SDTServer                      0x102a22fec closure #1 in Server.processError(_:) + 4377161708 (<compiler-generated>:4377161708)
2  SDTServer                      0x10257ce90 thunk for @escaping @callee_guaranteed () -> () + 4372287120 (<compiler-generated>:4372287120)

这是有问题的代码(该区域的所有代码都是 Swift5):

    private let callbackRunQueue = DispatchQueue(label: "com.superdupertango.Server.CallbackRunQueue", qos: DispatchQoS.userInitiated, target: nil)
    var bodyCompletionBlocks: [String: ((Data?, Error?, String) -> Void)] = [:]

...

    private init() {
        NotificationCenter.default.addObserver(self, selector: #selector(self.processError(_:)), name: Notification.Name.SDTServerWriteFailed, object: nil)
    }

...

    @objc private func processError(_ notification: Notification) {
        guard let userInfo = notification.userInfo, let requestId = userInfo["requestId"] as? String else {
            return
        }
        self.callbackRunQueue.async {
            DLog("Server.processError (\(requestId)): Got Error for request. Shutting down request.")
            guard let bodyCompletionBlock = self.bodyCompletionBlocks[requestId] else {
                DLog("Server.processError (\(requestId)): Failed getting body completion block. Returning")
                return
            }
            bodyCompletionBlock(Data(), nil, requestId)
            self.bodyCompletionBlocks.removeValue(forKey: requestId)
            self.initialCompletionBlocks.removeValue(forKey: requestId)
        }
    }

请注意,这callbackRunQueue是一个串行队列。

在 中检索的唯一字典值callbackRunQueueself.bodyCompletionBlocks

            guard let bodyCompletionBlock = self.bodyCompletionBlocks[requestId] else {

我发现了一些关于这个错误的引用,但他们都说这可能是一个多线程访问问题。

但是,在我的代码中,只有 3 个地方可以访问self.bodyCompletionBlocks,并且它们都在callbackRunQueue.asyncorcallbackRunQueue.sync块内。另请注意,其中一些代码在 GCDWebServer 的线程内运行,但正如我所提到的,我始终确保代码在我的callbackRunQueue队列中运行,所以我认为这与 GCDWebServer 无关。

我认为将线程敏感代码包含在串行队列的异步或同步块中可以防止这样的多线程访问问题。

有任何想法吗?

谢谢!

4

0 回答 0