Crash if the REM client receive incoming call in background
Steps:
- Init and start the ACBUC session in multithreading mode.
- Log in REM client -> put in background
- Waiting for the incoming call, and do not do anything on callee side.
- End the call from caller side.
Result:
App crash
Expected:
App should not crash
Workaround:
Re-launch REM client app
Config:
REM server version: REM-10.6.1.10000-8
REM client SDK version: 2.1.31.1.1
Finesse version: 10.5.1
REM client iOS: 9.1
User impact:
After app crash, the session is disconnect and can not receive call.
Attach the crash log.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks for the report. I've passed it back to the development team to investigate.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks for the quick reply.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hi Carson,
Sorry for the delay in responding.
We have not been able to reproduce this issue but in the steps to reproduce you mentioned:
- Init and start the ACBUC session in multithreading mode.
Did you modify the sample code?
And if so can you provide a code snippet?
Thanks,
Rob
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hi Rob,
You are welcome.
That's indeed to modify the sample code for reproducing this issue, just do not init the UC session on the main thread, the issue is 100% reproducible.
We can do just enough to reproduce this issue:
- In ConnectivityManager.m , do not init the UC session on main thread, add some code in Bold:
-(void)dataLoaded:(NSData *)nsData
{
// nsData will be empty on logout.
if (nsData.length > 0)
{
NSError *error = nil;
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:nsData options:0 error:&error];
if (error != nil)
{
NSLog(@"Error decoding JSON response from REST login API: %@", [error localizedDescription]);
// TODO display error
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Login/Logout failed!" message:[NSString stringWithFormat:@"Failed to log in/out. %@", [error localizedDescription]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[self hider:NO];
}
else
{
configuration = [response objectForKey:@"sessionid"];
NSLog(@"Got session : %@", configuration);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// The following line of code creates a UC object using the configuration retrieved from the gateway
_uc = [ACBUC ucWithConfiguration:configuration delegate:self];
// The following code can be used instead if STUN is required
// NSArray* stunServers = [NSArray arrayWithObject:@"stun:stun.l.google.com:19302"];
// _uc = [ACBUC ucWithConfiguration:configuration stunServers:stunServers delegate:self];
[self registerForReachabilityCallback];
BOOL acceptUntrustedCertificates = [[[NSUserDefaults standardUserDefaults] objectForKey:@"acceptUntrustedCertificates"] boolValue];
[_uc acceptAnyCertificate:acceptUntrustedCertificates];
NSNumber *useCookiesNumber = [[NSUserDefaults standardUserDefaults] objectForKey:@"useCookies"];
_uc.useCookies = [useCookiesNumber boolValue];
[_uc startSession];
// _uc.phone is available, but please wait for ucDidStartSession before making a call.
CFRunLoopRun();
});
}
}
}
- After UC session started, we can get the incoming call signal, so we can remove all call back logic for eliminating interference, add code like these:
- (void) ucDidStartSession:(ACBUC *)uc
{
return;
[self hider:NO];
ImSampleAppDelegate *appDelegate = (ImSampleAppDelegate *)[UIApplication sharedApplication].delegate;
UITabBarItem *accountTab = appDelegate.tabbedViewController.tabBar.items.lastObject;
accountTab.badgeValue = nil;
automaticLoginReattempts = 0;
LoginViewController *loginViewController = appDelegate.loginViewController;
loginViewController.uc = _uc;
loginViewController.configuration = configuration;
// TODO - not to perform the segue if the user logged out manually, or in other words perform it only after a non-repeated login from the Login view controller. This is not causing a problem, anyway, as the segue doesn't seem to operate if the login form is not on top.
[loginViewController performSegueWithIdentifier:@"loginSegue" sender:self];
}
Do the same on all method of ACBUCDelegate and ACBClientCallDelegate and ACBClientPhoneDelegate that implement in ConnectivityManager.m and DialPadViewController.m :
- (void) phone:(ACBClientPhone*)phone didReceiveCall:(ACBClientCall*)call
{
return;
.......................
}
- (void) call:(ACBClientCall*)call didChangeStatus:(ACBClientCallStatus)status
{
return;
..........................
}
..............
- Now we can rebuild the sample code and run on iPad to reproduce the issue.
- Log in REM client -> put in background
- Waiting for the incoming call, and do not do anything on callee side.
- End the call from caller side.
- Then crash on callee side.
If there is any question on the reproduce step, let me know.
Thanks,
Carson
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks for the detailed response Carson I've passed it on to the dev team, Rob
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hi Carson,
It has been pointed out to me that all method invocations on the SDK, even to access read-only properties, must be made from the same thread.
This can be any thread, and not necessarily the main thread. Internally, the SDK can use other threads to increase responsiveness, but any delegate callbacks are made on this same thread that is used to invoke to the SDK.
Regards,
Rob
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hi Rob,
Yes, just according to this developing guide:
"This can be any thread, and not necessarily the main thread"
Only in this way can reproduce this bug.
As the code I showed before:
firstly, according to "This can be any thread, and not necessarily the main thread", so we DO NOT init ACBUC object and start UC session on the main thread.
secondly, according to "any delegate callbacks are made on this same thread that is used to invoke to the SDK", so we add "return" for all delegate callbacks for eliminating interference, that means we don't handle any logic and don't invoke any method and don't access any properties of the REM SDK while it callback.
Finally, following the steps I showed before, keep monitor on the console log, we can reproduce this bug:
- Use other threads to increase responsiveness for the REM SDK
- Now we can rebuild the sample code and run on iPad to reproduce the issue.
- Log in REM client -> put in background
- Waiting for the incoming call, and do anything on callee side.
- End the call from caller side.
- Then crash on callee side.
Thanks,
Carson
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comments
0 comments
Please sign in to leave a comment.