Issue description
With two different applications I experienced the following bug which eventually leads to a crash:
When the application is in the background and we keep sending stats through the WatchRTC_SDK.RTCStatsReport callback then the application CPU will keep rising, hanging, and eventually will lead the OS to terminate the app.
See graph below:
The profiler shows the same, with hangs, and also points to the WatchRTC SDK being the culprit for the hangs:
Cause
The following method func getStats(callback: @escaping (WatchRTC_SDK.RTCStatsReport) -> Void) provides the client with a callback object to be called later with available RTCStatsReport.
Following the example provided in the Vonage Demo App, this callback is saved and called possibly multiple times until a new callback is provided through the getStats delegate method.
When calling that saved callback while in the background, the WatchRTC will fail and eventually exhaust the thread, leading to a crash.
WatchRTC logs indicate that when going to the background everything seems to reinitialize properly:
WatchRTC log [DEBUG] - didEnterBackground
WatchRTC log [DEBUG] - disconnect
WatchRTC log [DEBUG] - Get stats timer stopped
WatchRTC log [DEBUG] - Socket disconnected
Unfortunately there is a clear issue with keeping on calling the callbacks from the getStats delegate method.
Possible fixes
1. Do not call the callback when in background
Simple patch. Call callback only when UIApplication.shared.applicationState != .background`
class WatchRTCClientLive {
private var rtcStatsReportCallback: ((WatchRTC_SDK.RTCStatsReport) -> Void)?
func sendRtcStatReport(jsonArrayOfReports: String) {
guard let rtcStatReport = parseRTCStatsJsonString(jsonArrayOfReports: jsonArrayOfReports) else {
return
}
if let rtcStatsReportCallback, UIApplication.shared.applicationState != .background {
rtcStatsReportCallback(rtcStatReport)
}
}
}
extension WatchRTCClientLive: RtcDataProvider {
func getStats(callback: @escaping (WatchRTC_SDK.RTCStatsReport) -> Void) {
rtcStatsReportCallback = callback
}
}
2. Only ever call the callback once
Once consumed, set the callback to nil and never call it again. This works because the getStats delegate method will not trigger while in the background, as expected.
class WatchRTCClientLive {
private var rtcStatsReportCallback: ((WatchRTC_SDK.RTCStatsReport) -> Void)?
func sendRtcStatReport(jsonArrayOfReports: String) {
guard let rtcStatReport = parseRTCStatsJsonString(jsonArrayOfReports: jsonArrayOfReports) else {
return
}
if let rtcStatsReportCallback {
rtcStatsReportCallback(rtcStatReport)
self.rtcStatsReportCallback = nil
}
}
}
extension WatchRTCClientLive: RtcDataProvider {
func getStats(callback: @escaping (WatchRTC_SDK.RTCStatsReport) -> Void) {
rtcStatsReportCallback = callback
}
}
Comments
Both fixes (1) and (2) are only patches to the underlying issue.
I personally find it very odd for an iOS SDK to provide an API with a callback that is meant to be used multiple times, while at the same time updating this callback on a regular basis. This feels like an anti-pattern to me.
Thank you
Issue description
With two different applications I experienced the following bug which eventually leads to a crash:
When the application is in the background and we keep sending stats through the
WatchRTC_SDK.RTCStatsReportcallback then the application CPU will keep rising, hanging, and eventually will lead the OS to terminate the app.See graph below:
The profiler shows the same, with hangs, and also points to the
WatchRTCSDK being the culprit for the hangs:Cause
The following method
func getStats(callback: @escaping (WatchRTC_SDK.RTCStatsReport) -> Void)provides the client with a callback object to be called later with availableRTCStatsReport.Following the example provided in the Vonage Demo App, this callback is saved and called possibly multiple times until a new callback is provided through the
getStatsdelegate method.When calling that saved callback while in the background, the WatchRTC will fail and eventually exhaust the thread, leading to a crash.
WatchRTClogs indicate that when going to the background everything seems to reinitialize properly:Unfortunately there is a clear issue with keeping on calling the callbacks from the
getStatsdelegate method.Possible fixes
1. Do not call the callback when in background
Simple patch. Call callback only when UIApplication.shared.applicationState != .background`
2. Only ever call the callback once
Once consumed, set the callback to
niland never call it again. This works because thegetStatsdelegate method will not trigger while in the background, as expected.Comments
Both fixes (1) and (2) are only patches to the underlying issue.
I personally find it very odd for an iOS SDK to provide an API with a callback that is meant to be used multiple times, while at the same time updating this callback on a regular basis. This feels like an anti-pattern to me.
Thank you