socketio / socket.io-client-swift

Other
5.22k stars 842 forks source link

Crash when socket is closed by the server #563

Open jayjac opened 8 years ago

jayjac commented 8 years ago

Hi, I get the following crash on my iOS whenever socket.disconnect() is called from the Node.js server.

cropped

If socket.disconnect() is called from Swift code, I do not have this issue. Should I initialise the socket object with some special parameter to solve this problem ? I am using XCode 8/Swift 3 and the latest socket.io-client-swift.

Thanks for your help.

dominikweifieg commented 8 years ago

Same exception thrown here.

michaelfreund commented 7 years ago

Same issue here with 8.1.1, Xcode Version 8.1 (8B62) and Swift 3.

We're using https://github.com/facundoolano/socketio-auth on the server side to manage socket authentication. If authentication fails, the server will emit "unauthorized" and close connection.

We're receiving the event emitted from the server with socket.on("unauthorized"), but immediately after that, the app crashes on the same line as seen in the screenshot by @jayjac.

michaelfreund commented 7 years ago

In SwiftIOClient.swift either adding attributes: .concurrent to

private let parseQueue = DispatchQueue(label: "com.socketio.parseQueue", attributes: .concurrent)

or changing parseQueue.sync to parseQueue.async in public func engineDidClose did solve the problem.

But I'm very new to Swift & iOS development. So i'm not quite sure, let's say ... what I'm doing 🙈

Any help would be highly appreciated

dominikweifieg commented 7 years ago

Ok, did some more debugging. The problem is parseQueue.sync in the engineDidClose function of SocketIOClient.

The engineDidClose function is called by two threads at the same time and the parseQueue.sync then blocks both threads.

Here is the first thread:

socket io_2

And here the second:

socket io_1

As @michaelfreund wrote, changing parseQueue.sync to parseQueue.async solves the problem. Both threads will arrive in the function and both will trigger an asynchronous removeAll on the waiting packets.

Another solution would be to make sure that SocketIOClient.engineDidClose gets called only once, which in turn means that SocketEngine.closeOutEngine gets called only once. It currently gets called twice SocketEngine.disconnect, once through the call to disconnectPolling and once directly in the guard condition at the beginning of the function.

nuclearace commented 7 years ago

Does this still happen after the DispatchQueue refactors?

jayjac commented 7 years ago

I haven't been able to reproduce the crash so it seems like it's been fixed.

Thanks.