-
Notifications
You must be signed in to change notification settings - Fork 31
[BUG] Possible deadlock in Async subjects #52
Copy link
Copy link
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
It looks like subject can deadlock if task, that is observing its values is cancelled at the same time as send is called on it
Thread 1:
AsyncBufferedChannel.sendacquiresos_unfair_lockAsyncBufferedChannel.sendattempts to resume continuation returning element- Resuming continuation attempts to acquire internal lock for task status
Thread 2:
- Task that awaits for values from subject is cancelled. This acquires internal lock for task state
unregister()is called and attempts to acquireos_unfair_lock
Thread 1 has os_unfair_lock, waits for internal lock
Thread 2 has internal lock, waits for os_unfair_lock
Situation can be reproduced with test like this, if run repeatedly for 100 times:
@Test
func send_deadlocks_when_cancelled_concurrently() throws {
let subject = AsyncPassthroughSubject<Int>()
let t1 = Task.detached {
for await _ in subject { }
}
let barrier = DispatchSemaphore(value: 0)
let done = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
barrier.wait()
t1.cancel()
done.signal()
}
DispatchQueue.global().async {
barrier.wait()
subject.send(1)
done.signal()
}
barrier.signal()
barrier.signal()
done.wait()
done.wait()
}
It can also be reproduced using strict concurrency only, but setting up actual parallel execution is more complicated.
Additional context
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working