centrifugal / centrifuge-swift

Swift client SDK for bidirectional real-time communication with Centrifugo and Centrifuge-based server over WebSocket
MIT License
47 stars 41 forks source link

Crash in handleAsyncData(data:) #61

Closed seidju closed 2 years ago

seidju commented 2 years ago

Hello! We faced multiple crashes in method handleAsyncData(data:)

We're using 0.4.2 version in our app

Stack trace:

Crashed: com.centrifugal.centrifuge-swift.sync<A3640EA9-3604-4193-863B-41F57316740F>
0  SwiftCentrifuge                0x104e0 CentrifugeClient.handleAsyncData(data:) + 4393944288 (<compiler-generated>:4393944288)
1  SwiftCentrifuge                0xc63c closure #1 in CentrifugeClient.onData(data:) + 699 (Client.swift:699)
2  SwiftCentrifuge                0x5384 thunk for @escaping @callee_guaranteed () -> () + 4393898884 (<compiler-generated>:4393898884)
3  libdispatch.dylib              0x2914 _dispatch_call_block_and_release + 32
4  libdispatch.dylib              0x4660 _dispatch_client_callout + 20
5  libdispatch.dylib              0xbde4 _dispatch_lane_serial_drain + 672
6  libdispatch.dylib              0xc958 _dispatch_lane_invoke + 392
7  libdispatch.dylib              0x171a8 _dispatch_workloop_worker_thread + 656
8  libsystem_pthread.dylib        0x10f4 _pthread_wqthread + 288
9  libsystem_pthread.dylib        0xe94 start_wqthread + 8
seidju commented 2 years ago

@FZambia maybe I figured out why it could crash. Access to specific subscription in serverSubs is happening asynchronously, so at that moment we can't be sure, that specific object exists for key (channel). Unwrapping is performing on another thread.

private func handleAsyncData(data: Data) throws {
//...
  if let _ = self.serverSubs[channel] {
    self.delegateQueue.addOperation {
      var info: CentrifugeClientInfo? = nil;
      if pub.hasInfo {
        info = CentrifugeClientInfo(client: pub.info.client, user: pub.info.user, connInfo: pub.info.connInfo, chanInfo: pub.info.chanInfo)
       }
      let event = CentrifugeServerPublishEvent(channel: channel, data: pub.data, offset: pub.offset, info: info)
      self.delegate?.onPublish(self, event)

      // remove force unwrap
      if self.serverSubs[channel]?.recoverable == true && pub.offset > 0 {
        self.serverSubs[channel]?.offset = pub.offset
      }
    }
//...
}
FZambia commented 2 years ago

@seidju hello, I think makes sense - most probably I blindly added force unwrapping by applying the wrong XCode auto fix suggestion.

seidju commented 2 years ago

@FZambia could make a PR for this fix, so we could use updated version of framework in our production app?

FZambia commented 2 years ago

Yep, thanks a lot

FZambia commented 2 years ago

Closing, let's hope fix from #62 resolves a crash, please re-open if it's still an issue after updating.