Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash at PushNotifications.swift:39 #191

Open
FilipeAVS opened this issue Dec 12, 2024 · 3 comments
Open

Crash at PushNotifications.swift:39 #191

FilipeAVS opened this issue Dec 12, 2024 · 3 comments

Comments

@FilipeAVS
Copy link

FilipeAVS commented Dec 12, 2024

We had a few crashes being reported to Crashlytics with the following stack trace:

          Crashed: com.pusher.beams.handleMessageQueue
0  redacted-app               0xdd2b74 closure #1 in PushNotifications.serverSyncHandler.getter + 39 (PushNotifications.swift:39)
1  redacted-app               0xde8e0c ServerSyncProcessHandler.processSetUserIdJob(userId:) + 306 (ServerSyncProcessHandler.swift:306)
2  redacted-app              0xde79e8 closure #1 in ServerSyncProcessHandler.processJob(_:) + 209 (ServerSyncProcessHandler.swift:209)
3  redacted-app               0xde7398 ServerSyncProcessHandler.processJob(_:) + 189 (ServerSyncProcessHandler.swift:189)
4  redacted-app               0xde9614 ServerSyncProcessHandler.handleMessage(serverSyncJob:) + 379 (ServerSyncProcessHandler.swift:379)
5  redacted-app               0xdeb3c8 partial apply for closure #1 in closure #1 in ServerSyncProcessHandler.init(instanceId:getTokenProvider:handleServerSyncEvent:) + 60 (ServerSyncProcessHandler.swift:60)
6  redacted-app               0xdd8b24 thunk for @escaping @callee_guaranteed () -> () + 6283756
7  libdispatch.dylib              0x2370 _dispatch_call_block_and_release + 32
8  libdispatch.dylib              0x40d0 _dispatch_client_callout + 20
9  libdispatch.dylib              0xb6d8 _dispatch_lane_serial_drain + 744
10 libdispatch.dylib              0xc1e0 _dispatch_lane_invoke + 380
11 libdispatch.dylib              0x17258 _dispatch_root_queue_drain_deferred_wlh + 288
12 libdispatch.dylib              0x16aa4 _dispatch_workloop_worker_thread + 540
13 libsystem_pthread.dylib        0x4c7c _pthread_wqthread + 288
14 libsystem_pthread.dylib        0x1488 start_wqthread + 8

The issue might be here:

private lazy var serverSyncHandler = ServerSyncProcessHandler.obtain(
    instanceId: self.instanceId,
    getTokenProvider: { return PushNotifications.shared.tokenProvider[self.instanceId] }, <---- HERE!
    handleServerSyncEvent: { [weak self] event in
        self?.serverSyncEventHandler.handleEvent(event: event)
    }
)

instanceId can still be nil when serverSyncHandler is accessed, or maybe there is a race condition. On our side, we start the instance and set the user ID as expected. Any idea what could be happening and what we could do on our side to fix this? Thanks in advance.

Additional info

SDK: 4.0.0
iOS: 18.1.1

@aonemd
Copy link
Member

aonemd commented Dec 13, 2024

Hey @FilipeAVS , I guess you are unable to replicate this in your build?

To help us debug this, could you create a simple app that reflects your implementation and upload it so that we can try to re-produce the issue and also to make sure nothing stands out in the implementation? 🙏

@FilipeAVS
Copy link
Author

Hey @aonemd! Exactly, I am unable to replicate the issue, and we have a very low count of users who experienced the same issue, so this might be a very specific edge case.

As for the implementation, hope you don't mind that I share here a snippet that represents how we are implementing it.

So from different parts of the app, we call the initialize function on our PushNotificationsManager class.

final class PushNotificationsManager {
    static let shared = PushNotificationsManager()

    private let userStore: UserStore
    private let client = PushNotifications.shared

    private init(userStore: UserStore = UserStore.shared) {
        self.userStore = userStore
    }
}

// MARK: - Public Methods
extension PushNotificationsManager {
    func initialize() {
        startInstance()
        setUser()
    }
}

// MARK: - Private Methods
private extension PushNotificationsManager {
    func startInstance() {
        client.start(instanceId: "...")
        client.registerForRemoteNotifications()
    }

    func setUser() {
        guard
            let accessToken = userStore.accessToken,
            let userId = userStore.userId
        else { return }

        let tokenProvider = BeamsTokenProvider(authURL: "...") { () -> AuthData in
            let headers = ["Authorization": "Bearer \(accessToken)"]
            let queryParams: [String: String] = [:]
            return AuthData(headers: headers, queryParams: queryParams)
        }
        
        client.setUserId(userId, tokenProvider: tokenProvider) { error in
            if let error {
                print("Failed to authenticate to PushNotifications with error: \(error.localizedDescription)")
                return
            }
            print("Successfully authenticated with PushNotifications")
        }
    }
}

With the above, in various contexts (like resuming the app, logging in, etc.) we call the initialize method.

PushNotificationsManager.shared.initialize()

This is the general implementation that we are using. Could it be that since we are calling the initialize method from different places, and some of them are very close to each other, we are hitting some race conditions? I appreciate your help @aonemd!

@aonemd
Copy link
Member

aonemd commented Jan 3, 2025

Hey @FilipeAVS thanks for posting your implementation! I have been trying to reproduce this with no success so far.

This might be related to #190 btw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants