handle errors during debugserver startup and add helper function to start session (#459)
diff --git a/src/ios-deploy/ios-deploy.m b/src/ios-deploy/ios-deploy.m
index c20db70..0339cf0 100644
--- a/src/ios-deploy/ios-deploy.m
+++ b/src/ios-deploy/ios-deploy.m
@@ -989,11 +989,42 @@
CFRelease(s);
}
+void connect_and_start_session(AMDeviceRef device) {
+ AMDeviceConnect(device);
+ assert(AMDeviceIsPaired(device));
+ check_error(AMDeviceValidatePairing(device));
+ check_error(AMDeviceStartSession(device));
+}
+
void start_remote_debug_server(AMDeviceRef device) {
- ServiceConnRef con;
-
- check_error(AMDeviceSecureStartService(device, CFSTR("com.apple.debugserver"), NULL, &con));
+ ServiceConnRef con = NULL;
+ int start_err = AMDeviceSecureStartService(device, CFSTR("com.apple.debugserver"), NULL, &con);
+ if (start_err != 0)
+ {
+ // After we mount the image, iOS needs to scan the image to register new services.
+ // If we ask to start the service before it is found by ios, we will get 0xe8000022.
+ // In other cases, it's been observed, that device may loose connection here (0xe800002d).
+ // Luckly, we can just restart the connection and continue.
+ // In other cases we just error out.
+ NSLogOut(@"Failed to start debugserver: %x %s", start_err, get_error_message(start_err));
+ switch(start_err)
+ {
+ case 0xe8000022:
+ NSLogOut(@"Waiting for the device to scan mounted image");
+ sleep(1);
+ break;
+ case 0x800002d:
+ NSLogOut(@"Reconnecting to device");
+ // We dont call AMDeviceStopSession as we cannot send any messages anymore
+ check_error(AMDeviceDisconnect(device));
+ connect_and_start_session(device);
+ break;
+ default:
+ check_error(start_err);
+ }
+ check_error(AMDeviceSecureStartService(device, CFSTR("com.apple.debugserver"), NULL, &con));
+ }
assert(con != NULL);
gdbfd = AMDServiceConnectionGetSocket(con);
/*
@@ -1112,10 +1143,7 @@
CFStringRef device_full_name = get_device_full_name(device),
device_interface_name = get_device_interface_name(device);
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
NSLogOut(@"------ Debug phase ------");
@@ -1414,10 +1442,7 @@
// Used to send files to app-specific sandbox (Documents dir)
AFCConnectionRef start_house_arrest_service(AMDeviceRef device) {
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
AFCConnectionRef conn = NULL;
@@ -1575,10 +1600,7 @@
void list_bundle_id(AMDeviceRef device)
{
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
NSArray *a = [NSArray arrayWithObjects:
@"CFBundleIdentifier",
@@ -1841,10 +1863,7 @@
if (cf_uninstall_bundle_id == NULL) {
on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", [NSString stringWithUTF8String:app_path]);
} else {
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0);
if (code == 0) {
@@ -1941,10 +1960,7 @@
if (cf_uninstall_bundle_id == NULL) {
on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", [NSString stringWithUTF8String:app_path]);
} else {
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0);
if (code == 0) {
@@ -1962,10 +1978,7 @@
NSLogOut(@"------ Install phase ------");
NSLogOut(@"[ 0%%] Found %@ connected through %@, beginning install", device_full_name, device_interface_name);
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
CFDictionaryRef options;
if (app_deltas == NULL) { // standard install
@@ -1981,10 +1994,7 @@
check_error(AMDeviceSecureTransferPath(0, device, url, options, transfer_callback, 0));
close(*afcFd);
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
check_error(AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0));
} else { // incremental install
check_error(AMDeviceStopSession(device));
@@ -2032,10 +2042,7 @@
CFIndex size = sizeof(keys)/sizeof(CFStringRef);
options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, size, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- AMDeviceConnect(device);
- assert(AMDeviceIsPaired(device));
- check_error(AMDeviceValidatePairing(device));
- check_error(AMDeviceStartSession(device));
+ connect_and_start_session(device);
check_error(AMDeviceSecureInstallApplicationBundle(device, url, options, incremental_install_callback, 0));
CFRelease(extracted_bundle_id);
CFRelease(deltas_path);