zwopple / PocketSocket

Objective-C websocket library for building things that work in realtime on iOS and OS X.
Other
414 stars 129 forks source link

Deadlock or crash in -[PSWebSocket dealloc] #55

Open snej opened 8 years ago

snej commented 8 years ago

Occasionally -[PSWebSocket dealloc] will either deadlock (iOS ≤ 9) or crash (iOS 10). The cause is the same — calling dispatch_barrier_sync(_workQueue, ...) when it's already running on the _workQueue. The behavior changes because libDispatch in iOS 10 [and presumably macOS 10.12] detects the deadlock condition and triggers a crash instead, adding to the crash report "CRASH_INFO_ENTRY_0 BUG IN CLIENT OF LIBDISPATCH: dispatch_barrier_sync called on queue already owned by current thread".

I am not sure how to fix this. The PSWebSocket is used on multiple queues/threads, so it's indeterminate which of those will make the last -release call and trigger -dealloc. If it happens to be the workQueue, the synchronous GCD dispatch to it will deadlock.

But I'm not sure removing the GCD call is not a good fix because, if -dealloc runs on a different queue, the -disconnect method would run on that queue, violating thread-safety.

On the other other hand, though, if the object is in -dealloc, that implies no other threads have references to it so there couldn't be simultaneous calls to it on other threads. Which means it should be thread-safe to operate on its ivars.

(FYI, there was an old abandoned PR #26 for doing exactly this.)

snej commented 8 years ago

The crash was reported against Couchbase Lite. We use a modified version of PS, but I don't think this behavior has changed.

passuf commented 7 years ago

I am observing the same problem in [PSWebSocketServer dealloc]. Calling disconnect directly seems to work for a PSWebSocket client, but I am not sure if I can do the same thing for the server.

Has anyone found a good solution to prevent the deadlock?

szuwest commented 6 years ago

I met this problem too, when I stop the server.