dispatch_group_leave crash in swift
Asked Answered
G

2

19

This happens very rarely. Here is the last line of the stack trace:

0  libdispatch.dylib              0x0000000197a85a9c dispatch_group_leave + 48

dispatch_group_leave is called in a complete closure which is invoked like this:

  dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                { () -> Void in
                    let query = HKStatisticsCollectionQuery(quantityType: quantityType,
                        quantitySamplePredicate: nil,
                        options: statisticOptions,
                        anchorDate: anchorDate,
                        intervalComponents: interval)
                    query.initialResultsHandler = {

                        complete()

So we dispatch to a background thread, run a HKStatisticsCollectionQuery, and then call a function parameter closure called complete. Inside complete is where the dispatch_group_leave is called and the crash happens.

Any ideas are most appreciated! Thanks!

Gamogenesis answered 27/5, 2015 at 4:25 Comment(1)
G
29

If dispatch_group_leave call isn't balanced with dispatch_group_enter then crash may happen.

Germinant answered 27/5, 2015 at 6:3 Comment(5)
Interesting. I have an enter before the first closure is called. hmmm.Gamogenesis
I think this was it. Certain leaves were getting called too fast. Moved all the enters and the notify to before the leaves can be called. Thanks!Gamogenesis
@Germinant is there a way to prevent the case of calling dispatch_group_leave more than it should? i.e., for cases that I can't tell for sure that completion block - of which in it the dispatch_group_leave is called - will not be called more than once?Intrigant
@Intrigant did you find a way?Defloration
We can add a little bit sleep thread call after dispatch_group_leave. It will help dispatch_group to apply concurrency rules. It saved my day.Misguide
H
9

In the worst case, you can check the discount group's count via its debugDescription String:

let count = self.groupExecuting.debugDescription.components(separatedBy: ",").filter({$0.contains("count")}).first!.components(separatedBy: CharacterSet.decimalDigits.inverted).filter({Int($0) != nil})
assert(count.first != "0")

This strategy is further explored in this question: DispatchGroup: check how many "entered"

Huntingdon answered 4/3, 2019 at 19:14 Comment(2)
What in tarnationMoy
@PranoyC This should obviously not be used in the production code, but was really helpful for debugging.Isfahan

© 2022 - 2024 — McMap. All rights reserved.