Peculiar EXC_BAD_ACCESS, involving a Task

I had to update a simple piece of code, so it could be delayed by a few ms in some cases. This is how I tried to achieve that, by using a Task:

class SomeClass {
    private var availableStuff : Set<Stuff> = []

    func updateStuff(lookingFor prop: SomeProp,
                     updatedThing: String,
                     waiting: Duration = .zero)
    {
        Task {
            if waiting != .zero {
                try await Task.sleep(for: waiting)
            }
            
            if var stuff = availableStuff.first(where: { $0.prop == prop }) {
                stuff.thing = updatedThing
//                print(availableStuff)
                self.availableStuff.remove(stuff)
                self.availableStuff.insert(stuff) // BAD ACCESS here
            }
        }
    }
}

It did work before implementing the delay, but now it would crash at the insert statement (sometimes at remove). Naively, I put a print statement beforehand and to my surprise, this kept the crash from occurring at all!

I switched on Address Sanitizer, now it doesn't crash, even w/o the print statement.

  • Am I using the Task wrong, somehow?
  • How can I further diagnose this, so it doesn't happen later in production?
  • Or should I just leave the print in and hope for the best?

Thanks!

You don’t show the code that reads the availableStuff property. However, I suspect that’s the cause of your problem. When you run async code, it runs on a thread from the Swift concurrency pool. Unless you have some other code to serialise your access to availableStuff with the other code that’s accessing it, you have a concurrency bug.

I switched on Address Sanitizer

Such is the nature of thread-safety issues. Try enabling TSan.

Also, consider converting SomeClass to an actor and then enabling strict concurrency checking. The goal of Swift concurrency is to rule out this entire class of bugs by having the compiler statically enforce thread safety.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Peculiar EXC_BAD_ACCESS, involving a Task
 
 
Q