Skip to content

closure #1 in HttpConnection.transportDidClose(_:) + 274 (HttpConnection.swift:274) #311

@sspogra

Description

@sspogra

I am looking at issues weekly. Urgent issues can be prioritized.

My Swift SignalR Client Course contains the most complete and up-to-date information about using the client.

Please provide the details below to avoid unnecessary turnaround:

  • Client version - 1.1.0 It is from SPM
  • Describe the bug - App is crashing randomly for a user once daily
  • Expected behavior - Crashing when any event received from api side not all time crashed only once a day.
  • Code To Reproduce the Issue - Below is my app code that show uses of SignalR

class DataDownloadManager: NSObject, DataDownloadOperationDelegate {

static let sharedManager = DataDownloadManager()

private var hubConnection: HubConnection?

private var isConnecting = false

func addDownloadListener(){

    let userId = Injector.prefs.getCurrentUserId()
    
    if userId == nil || userId! <= 0 {
        self.removeDownloadListener()
        return;
    }
    
    self.startConnection()
}

private let signalRQueue = DispatchQueue(label: "com.signalr.queue", qos: .background)


private func startConnection(){
    
    signalRQueue.async { [weak self] in
        
        guard let self = self else { return }
        
        guard let url = URL(string: Secrets.apiBaseURL + "/signalr") else {
            print("Invalid SignalR URL")
            return
        }
        
        self.hubConnection = HubConnectionBuilder(url: url)
            .withHubConnectionDelegate(delegate: self)
            .withLogging(minLogLevel: .error)
            .build()
        
        self.setUpMessageHandlers()
        self.isConnecting = true
        self.hubConnection?.start()
    }
}

private func reconnect() {
    signalRQueue.asyncAfter(deadline: .now() + 5.0) { [weak self] in
        guard let self = self, !self.isConnecting else { return }
        self.startConnection() // Use the same queue
    }
}

private func setUpMessageHandlers() {

    signalRQueue.async { [weak self] in
        // Use the 'on' method to subscribe to messages with the specified method name
        
        guard let self = self, let hubConnection = self.hubConnection, AppUtils.isEmpty(value: hubConnection.connectionId) else {
            print("DataDownloadManager:setUpMessageHandlers: hubConnection already have connectionId")
            return
        }
        
        hubConnection.on(method: "guard_app_updates", callback: { (guardId: Int, adminId: Int, data: DataDownloadRespone) in
            if AppUtils.noInternet(){
                print("DataDownloadManager:no internet connection so not setting next operation.");
                return
            }
            
            let downloadOperation = DataDownloadOperation(data: data, delegate: self)
            
            self.operationQueue.addOperation(downloadOperation)
        })
        
    }
}

func removeDownloadListener() {
    signalRQueue.async { [weak self] in
        guard let self = self else { return }
        if let connection = self.hubConnection {
            connection.stop()
            self.hubConnection = nil
        }
        self.isConnecting = false
    }
}

}

extension DataDownloadManager: HubConnectionDelegate{

func connectionDidOpen(hubConnection: SignalRClient.HubConnection) {
    // print("connectionDidOpen:",hubConnection)
    self.isConnecting = false
    
    if AppUtils.noInternet(){
        return
    }
    
    guard let connectionId = hubConnection.connectionId else {
        return
    }
    
    DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 2) {
        Injector.authRepository.updateGuardSignalrId(connectionId) { resource in
            if let success = resource as? Resource<LoginResponse>.Success{
                if let response = success.value {
                    print("updateGuardSignalrId:success:",response.toJson())
                }
            }else if  let error = resource as? Resource.Failure{
                print("updateGuardSignalrId:error:",error)
            }
        }
    }
    
}

func connectionDidFailToOpen(error: Error) {
    print("connectionDidFailToOpen:",error)
    self.isConnecting = false
    self.reconnect()
}

func connectionDidClose(error: Error?) {
    print("connectionDidClose:", error?.localizedDescription ?? "")
    signalRQueue.async { [weak self] in
        guard let self = self else { return }
        self.hubConnection = nil
        self.isConnecting = false
        if error != nil {
            self.reconnect()
        }
    }
}

func connectionWillReconnect(error: Error) {
    print("connectionWillReconnect")
}

func connectionDidReconnect() {
    print("connectionDidReconnect")
}

}

  • Additional context -
    Crashed: SignalR.connection.callbackQueue
    0 App Name 0xb48eb8 closure Remaining work #1 in HttpConnection.transportDidClose(_:) + 274 (HttpConnection.swift:274)
    1 App Name 0x10e54 <deduplicated_symbol> + 4337864276
    2 libdispatch.dylib 0x1aac _dispatch_call_block_and_release + 32
    3 libdispatch.dylib 0x1b584 _dispatch_client_callout + 16
    4 libdispatch.dylib 0xa2d0 _dispatch_lane_serial_drain + 740
    5 libdispatch.dylib 0xadac _dispatch_lane_invoke + 388
    6 libdispatch.dylib 0x151dc _dispatch_root_queue_drain_deferred_wlh + 292
    7 libdispatch.dylib 0x14a60 _dispatch_workloop_worker_thread + 540
    8 libsystem_pthread.dylib 0xa0c _pthread_wqthread + 292
    9 libsystem_pthread.dylib 0xaac start_wqthread + 8

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions