Data race occurring in Swift Actor

629 views Asked by At

I found a data race in my Swift app by using the Thread Sanitizer, and so I made my first attempt to fix race conditions by converting the offending class to an actor. The crash that the race was causing seems to have gone away, but Thread Sanitizer is still saying there's a data race in the code, which I thought should be impossible in the actor.

I can't post the entire actor here, but here is the code where the race is occurring:

actor SampleActor {
    private var things = Set<Int>()
    
    func addThing(_ newThing: Int, seconds: Double) {
        things.insert(newThing)
        Task {
            try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
            self.things.remove(newThing)
        }
    }
}

// Code to cause the race
let sample = SampleActor()
for n in 0 ..< 1000 {
    Task {
        await sample.addThing(n, seconds: Double.random(in: 0...1.0))
    }
}


I'm probably going about this the wrong way, but I need to add an object to the SampleActor's set of objects, and have it be automatically removed after some amount of time.

Is there a better way to do this? And what am I missing about the use of actor to avoid the data race in this case? Shouldn't SampleActor.things be immune to races here because it's a property of an actor?

2

There are 2 answers

2
lorem ipsum On BEST ANSWER

Remove the Task { part in the actor

Add async to the function

func addThing(_ newThing: Int, seconds: Double) async {
2
Rob On

There is no data race here. This is a bug in TSAN. Reportedly they have been improving its interaction with actors, but as of Swift 5.7.2, at least, there are still issues. E.g., see https://github.com/apple/swift/issues/57902 or https://github.com/apple/swift/issues/57749.

As lorem ipsum said (+1), it is prudent to abandon the use of Task {…} in addThing, for more concise code that enjoys the benefits of structured concurrency, but that is not the issue here. For the time being, simply avoid using TSAN with Swift concurrency.