0

Steps to reproduce crash:
If semaphore.wait() is called and then deinitialize the view controller that owns it before calling semaphore.signal, app crashes.

Getting below error on dinit of the class:

EXC_BAD_INSTRUCTION with the message "BUG IN CLIENT OF LIBDISPATCH: Semaphore object deallocated while in use"

Used:

let semaphore = DispatchSemaphore(value: 1)

But weirdly adding below mentioned code under deinit fixes the crash issue, don't know why.

 while (semaphore.signal() != 0) {}

So is there any proper fix ?

  • Semaphores are a pretty low-level synchronization mechanism, and don't play very well with QoS (and are hard for the system to optimize around). Could you share a little bit more context here on how you're using this semaphore, and whether it might be possible to switch to something like a DispatchQueue instead? [Specifically, you can't deallocate a semaphore while something is waiting on it, but the thing waiting on the semaphore can be "far enough" away from the owner of the semaphore to not retain it. Much harder to do when using a queue.] – Itai Ferber Jan 13 '22 at 16:48
  • GCD/libdispatch has declared that the semaphore is “in use” at deallocation because the semaphore’s value at deinit was less than when it was at init. The simplest fix is to eliminate the path of execution where you `wait` and never perform the corresponding `signal` (e.g., `defer` the `signal` before any early exit, to make sure you `signal` regardless). If that’s not feasible, the other solution is to create the semaphore with a zero value and then `signal` to get it up to the value you want (one in this case). That way, even though the semaphore is still in use, GCD won't know. – Rob Jan 13 '22 at 19:17

0 Answers0