iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call

iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call

Description

I have successfully implemented VoIP pushes for the Killed state, where CallKit triggers correctly. However, when the app is in the Background state (suspended), it consistently crashes with an NSInternalInconsistencyException.

The app process is killed by the iOS Watchdog because it fails to satisfy the requirement of posting an incoming call in the same run loop as the push receipt, or the completion handler is not being released fast enough by the JS bridge.

Environment

  • React Native Version: .78
  • React Native CallKeep Version: 4.3.14
  • React Native VoIP Push Notification Version: 3.3.3
  • iOS Version: 18.x
  • Device: Physical iPhone [iphone 13 pro]

The Issue

When a VoIP push arrives while the app is in the Background:

  1. pushRegistry:didReceiveIncomingPushWithPayload: is called.
  2. RNCallKeep.reportNewIncomingCall is triggered on the Main Thread.
  3. The app is terminated by the system before the CallKit UI is fully established or before the completion() closure is executed.

Current Implementation (AppDelegate.swift)

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    
    let payloadDict = payload.dictionaryPayload
    let callerName = payloadDict["callerName"] as? String ?? "Unknown Caller"
    let callUUIDString = payloadDict["uuid"] as? String ?? UUID().uuidString
    let userGUID = payloadDict["guid"] as? String ?? "0"

    RNCallKeep.reportNewIncomingCall(
      callUUIDString,
      handle: userGUID,
      handleType: "generic",
      hasVideo: false,
      localizedCallerName: callerName,
      supportsHolding: true,
      supportsDTMF: true,
      supportsGrouping: true,
      supportsUngrouping: true,
      fromPushKit: true,
      payload: ["userGuid": userGUID],
      withCompletionHandler: { 
      }
    )

    RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue)
    completion()
  }

Logs

Exception Type:  EXC_CRASH (SIGKILL)
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: TCC 1 | 
[CoreFoundation] Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push.

Observed Behavior

  • Killed State: Works perfectly.
  • Foreground State: Works perfectly.
  • Background State: The phone may vibrate once, but the app process is killed before the CallKit UI appears.

Questions/Suspected Causes

  1. Is RNVoipPushNotificationManager.addCompletionHandler causing a delay in the background run loop that triggers the Watchdog?
  2. Should completion() be called immediately in Swift for the Background state, rather than waiting for VoipPushNotification.onVoipNotificationCompleted in JS?
  3. Is there a known issue with RNCallKeep not being able to present the UI while the app is in a suspended background state?

iOS App terminated by Watchdog (Signal 9) in Background state despite reporting call
 
 
Q