socket.io-client-swift icon indicating copy to clipboard operation
socket.io-client-swift copied to clipboard

handleAck crash

Open patmalt opened this issue 5 years ago • 8 comments

Screen Shot 2019-04-29 at 4 04 35 PM

Crashed Thread 3 :
--
0 | SocketIO | 0x103298e74 | handleAck () (<compiler-generated>:0)
1 | SocketIO | 0x103298e74 | handleAck () (<compiler-generated>:0)
2 | SocketIO | 0x10329969c | handlePacket () (SocketIOClient.swift:387)
3 | SocketIO | 0x1032abb4c | _parseEngineMessage () (SocketManager.swift:415)
4 | SocketIO | 0x1032aad14 | SocketIO + 224532
5 | SocketIO | 0x10327c2f8 | (unknown) (<compiler-generated>:0)

Has anyone else seen this crash before?

Should the SocketAckManager handle everything (including insert) on the socket client's handleQueue?

patmalt avatar Apr 29 '19 20:04 patmalt

This comment from SocketIOClient.swift makes me thing so...

**NOTE**: The client is not thread/queue safe, all interaction with the socket should be done on the `manager.handleQueue`

patmalt avatar Apr 30 '19 17:04 patmalt

I'm having a similar problem. The crash accours very rarely and randomly. I was not able to reproduce it on purpose.

Crashed: com.XYZ.socket
0  SocketIO                    	0x10194c9d4 specialized Set._Variant.insert(_:) (<compiler-generated>)
1  SocketIO                     	 0x10194b918 OnAckCallback.timingOut(after:callback:) + 66 (SocketAckManager.swift:66)
2  XYZ                       	0x100171ee8 specialized SocketModule.performMethod<A>(_:request:params:dispatchQueue:handler:) + 105 (<compiler-generated>:105)
3  XYZ                      	0x1002558d8 specialized static Api.fetchUserProfile(reloadHandler:) + 89 (AppState.swift:89)
4  XYZ                       	0x10032be00 XYZSocketManager.emitClient() (AppState.swift)
5  XYZ                       	0x10032a220 closure #1 in XYZSocketManager.registerServer() + 207 (XYZSocketManager.swift:207)
6  SocketIO                      0x10196cf44 specialized SocketIOClient.handleEvent(_:data:isInternalMessage:withAck:) (SocketIOClient.swift)
7  SocketIO                       0x101969d34 SocketIOClient.handlePacket(_:) (<compiler-generated>)
8  SocketIO                       0x10197bf7c specialized SocketManager._parseEngineMessage(_:) + 416 (SocketManager.swift:416)
9  SocketIO                       0x10197b144 partial apply for closure #1 in SocketManager.engineDidClose(reason:) + 4389892420
10 SocketIO                       0x10194bda4 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
11 libdispatch.dylib              0x18c550a38 _dispatch_call_block_and_release + 24
12 libdispatch.dylib              0x18c5517d4 _dispatch_client_callout + 16
13 libdispatch.dylib              0x18c52cdec _dispatch_lane_serial_drain$VARIANT$armv81 + 548
14 libdispatch.dylib              0x18c52d92c _dispatch_lane_invoke$VARIANT$armv81 + 408
15 libdispatch.dylib              0x18c535e08 _dispatch_workloop_worker_thread + 584
16 libsystem_pthread.dylib        0x18c731114 _pthread_wqthread + 304
17 libsystem_pthread.dylib        0x18c733cd4 start_wqthread + 4

kasyrm avatar Jul 26 '19 08:07 kasyrm

@kasyrm Please see my comment above. We were able to solve this crash by dispatching any interaction with an instance of SocketIOClient onto the manager.handleQueue.

patmalt avatar Jul 26 '19 16:07 patmalt

It seems it works, thanks!

kasyrm avatar Aug 19 '19 20:08 kasyrm

@patmalt Can you give me an example on how to actually use it. Do you mean it like this:

self.manager?.handleQueue.async {
            if self.socket?.status != .connected {
                self.connectSocket(handler: {
                    self.emitWithACK(withTimeoutAfter: 15, event: event, params: nil, array: array)
                })
            } else {
                self.emitWithACK(withTimeoutAfter: 15, event: event, params: nil, array : array)
            }
        }

Do I need to to perform this only for my emit calls? @kasyrm Can you help ?

aidevpk avatar Oct 02 '20 04:10 aidevpk

Yes, that's correct. We put EVERY interaction with the socket on the manager's queue. Did it help?

patmalt avatar Oct 02 '20 11:10 patmalt

func emit(with event: String , _ params : JSONDictionary?, timeoutAfter: Double = 15.0, ackHandler: (([Any]) -> Void)? = nil){
        self.manager?.handleQueue.async {
            self.connectSocket(handler: {
                self.emitWithACK(withTimeoutAfter: timeoutAfter, event: event, params: params, array: nil) {
                    ack in
                    ackHandler?(ack)
                }
            })
        }
    }

@patmalt Please confirm this method now. So I have a singleton class with this method. I am calling this emit method from different threads. is it okay ? and also let me know if I can do all my emits on Main Thread or will it impact the performance significantly ?

aidevpk avatar Oct 02 '20 12:10 aidevpk

To make it work I did all the emits on manager.handleQueue and then I would dispatch a response to whatever queue I needed.

kasyrm avatar Oct 02 '20 12:10 kasyrm