PSOperations icon indicating copy to clipboard operation
PSOperations copied to clipboard

"evaluateConditions() was called out-of-order" assert in Operation.swift is sometimes failing

Open therauli opened this issue 8 years ago • 2 comments

I have a rather big code base that was using the the code based on the the WWDC presentation code. I recently discovered PSOperations and updated our code base using that. Now for some reason the assert in Operation class evaluateConditions is failing when my operation inherited form GroupOperation gets cancelled.

I'm puzzled since the failure occurs rarely. The code base uses Operations and especially GroupOperatins heavily in down loading and parsing data from REST sources.

Why am I getting the assertion failure?

I'm using code from master (latest commit is 7947757c25181013df61a00bb538bfd0982e383f)

therauli avatar Jul 28 '16 12:07 therauli

We have made many changes around race conditions, are you seeing this problem with the latest version?

mcmurrym avatar Jan 25 '18 23:01 mcmurrym

I have encountered this issue as well and i have found a 100% reproducible case.

  1. Create a condition that is async (do a dispatch after 1 second and call completion with any result)
  2. Add the operation with that condition to queue and cancel immediately
  3. The operation will crash in debug build due to this assert, since the var isReady: Bool is returning true when the operation is cancelled, but state at this point is still .evaluatingConditions

What i did to fix this:

// Here is where we extend our definition of "readiness".
    override open var isReady: Bool {
        stateAccess.lock()
        defer { stateAccess.unlock() }

        guard super.isReady else { return false }

        guard !isCancelled else {
            // when operation gets cancelled during evaluate conditions an assert is raised, so prevent transition to `isReady` until conditions are finished evaluating since there's no cancellation of conditions
            return state != .evaluatingConditions
        }

        switch state {
        case .initialized, .evaluatingConditions, .pending:
            return false
        case .ready, .executing, .finishing, .finished:
            return true
        }
    }

DmitrijMaz avatar Oct 19 '20 15:10 DmitrijMaz