Using dispatch_once is very handy at times, however there may be times where your program comes to a halt, and can point blame to a dispatch_once wrapper. The key here is using the stack trace if possible to look at the chain of events and tracing it to see why a resource might be locked.
I have run across this scenario myself, pausing the application showed the following:
libsystem_kernel.dylib`semaphore_wait_trap: 0x23fbfac: movl $0xffffffdc, %eax 0x23fbfb1: calll 0x24024bc ; _sysenter_trap 0x23fbfb6: ret 0x23fbfb7: nop
Well that confirms that it is stuck. Now the stack trace. This is shown by clicking the thread state on the debug area. If there is more than one thread, try to find the one stuck on a semaphore wait.
Clicking ‘semaphore_wait_trap’ shows a list of what that thread has traveled through:
The blue icons represent code created by you that sit on top of the API. Here we see that I have multiple dispatch_once’s occurring. The issue was found when I noticed that I was calling the same dispatch_once. Look at 19 and 5 and you will see what I mean.. My logic had the init of an object call another object which tried to call the initial init I had started, which caused a deadlock as it was trying to wait for itself to complete. Keep your eye out for any recursive pattern you may have going on.