0

I know this question has been already asked several times, but either it stayed unanswered or the answer was totally not helping.

Here is my crash report :

enter image description here

This question and especially the comments helped me understand (kind of) my issue.

It seems from your crash log com.apple.root.background-qos, this is the thread request which might be over committed due to which it exist as it cannot take any more request.

If I understand it correctly, it may be possible that the thread handling requests might not be able to handle more requests ?

How do I debug and test this ? I am unable to reproduce the crash.

NB: In my launcher service I am doing 5 or 6 requests each one separated in a dispatchGroup.enter / .leave when finished, like this :

dispatchGroup.enter()
self.fetchObservationForecast(lat: lat, lon: lon) { result in
     switch result {
     case .success(let observationForecast) :
          print("Observation Forecast request succeeded")
          model["observationForecast"] = observationForecast
          break
     case .failure(let error) :
          print("Observation Forecast request failed : \(error)")
          model["observationForecast"] = error
          break
     }
     dispatchGroup.leave()
}

Am I looking at the wrong place ? How can I test and reproduce it in order to submit a fix ?

Any help would be appreciated.

  • 2
    The crash is coming from something in the closures in the LauncherService methods indicated. The top line in the trace indicates that you're crashing on setting a Dictionary value. Mutable Swift Dictionaries are not thread-safe, and that along with the background.qos pointer make me think you're reading/writing a Dictionary on multiple threads. It's probably something like the `model["observationForecast"] = ` code above doing that. – clarus Apr 15 '19 at 13:50
  • Thank you for this analysis. It will help me a lot. You can write an answer if you want the accepted answer, because I think you are right. –  Apr 15 '19 at 14:03
  • Thanks, good luck. – clarus Apr 15 '19 at 14:38

1 Answers1

1

The crash is coming from something in the closures in the LauncherService methods indicated. The trace indicates that you're crashing on setting a Dictionary value.

PartialStackTrace

Mutable Swift Dictionaries are not thread-safe, and that fact along with the background.qos indictor make me think you're reading/writing a Dictionary on multiple threads.

It's probably something like the model["observationForecast"] = code below doing that.

dispatchGroup.enter()
self.fetchObservationForecast(lat: lat, lon: lon) { result in
     switch result {
     case .success(let observationForecast) :
          print("Observation Forecast request succeeded")
          model["observationForecast"] = observationForecast
          break
     case .failure(let error) :
          print("Observation Forecast request failed : \(error)")
          model["observationForecast"] = error
          break
     }
     dispatchGroup.leave()
}
clarus
  • 2,455
  • 18
  • 19
  • What is the alternative of this non thread safe Mutable Dictionary ? –  Apr 15 '19 at 15:02
  • One approach may be to async dispatch all your model's dictionary access to the main thread. – clarus Apr 15 '19 at 15:17
  • Ok so what's the difference between your solution and this https://medium.com/@mohit.bhalla/thread-safety-in-ios-swift-7b75df1d2ba6? –  Apr 15 '19 at 15:27
  • That's pretty much what I'm talking about. That example doesn't require the main thread and is wrapped into a reusable class, but it's still doing all work on one thread. There's no reason your Dictionary access needs to run on the main thread, so using a different queue is arguably a better solution. The important thing is that all access happens on the same thread, whatever it is. – clarus Apr 15 '19 at 16:24