GRDB.swift: Deadlock in Pool.swift in v6.10.1

Since updating to 6.10, I’ve been seeing deadlocks with threads stuck at itemsSemaphore.wait() at Pool.swift line 80. The stack traces themselves aren’t hugely informative but I have a suspicion that something in v6.10 has lead to unbalanced calls to itemsSemaphore.signal() – possibly https://github.com/groue/GRDB.swift/pull/1350.

Screenshot 2023-04-12 at 16 47 42

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 19 (13 by maintainers)

Commits related to this issue

Most upvoted comments

I created a test that demonstrates the issue. I had to cheat the test timing by inserting a sleep (so it’s not for merging) but it demonstrates how observers can block the writing queue and vice versa, leading to a deadlock.

https://github.com/groue/GRDB.swift/pull/1364

It is definitely a deadlock (depending on your definition, it might also be called starvation/exhaustion but since the observers are blocked, it’s not a situation that will resolve). The writer is holding the queue and waiting for itemSemaphore which it will never get. The itemsSemaphore is meanwhile held by the observers who are all waiting for the queue which they will never get. The only solution is to enforce an ordering to these locks (e.g. you may not attempt to acquire itemSemaphore after queue).

I’ll try to construct a simple test case and follow up.