CB-8119 Restart adb when we detect it's hung
diff --git a/bin/templates/cordova/lib/build.js b/bin/templates/cordova/lib/build.js
index 85a6e7c..0d4d004 100644
--- a/bin/templates/cordova/lib/build.js
+++ b/bin/templates/cordova/lib/build.js
@@ -398,12 +398,44 @@
* Returns "arm" or "x86".
*/
module.exports.detectArchitecture = function(target) {
- return exec('adb -s ' + target + ' shell cat /proc/cpuinfo')
- .then(function(output) {
- if (/intel/i.exec(output)) {
- return 'x86';
+ function helper() {
+ return exec('adb -s ' + target + ' shell cat /proc/cpuinfo')
+ .then(function(output) {
+ if (/intel/i.exec(output)) {
+ return 'x86';
+ }
+ return 'arm';
+ });
+ }
+ // It sometimes happens (at least on OS X), that this command will hang forever.
+ // To fix it, either unplug & replug device, or restart adb server.
+ return helper().timeout(1000, 'Device communication timed out. Try unplugging & replugging the device.')
+ .then(null, function(err) {
+ if (/timed out/.exec('' + err)) {
+ // adb kill-server doesn't seem to do the trick.
+ // Could probably find a x-platform version of killall, but I'm not actually
+ // sure that this scenario even happens on non-OSX machines.
+ return exec('killall adb')
+ .then(function() {
+ console.log('adb seems hung. retrying.');
+ return helper()
+ .then(null, function() {
+ // The double kill is sadly often necessary, at least on mac.
+ console.log('Now device not found... restarting adb again.');
+ return exec('killall adb')
+ .then(function() {
+ return helper()
+ .then(null, function() {
+ return Q.reject('USB is flakey. Try unplugging & replugging the device.');
+ });
+ });
+ });
+ }, function() {
+ // For non-killall OS's.
+ return Q.reject(err);
+ })
}
- return 'arm';
+ throw err;
});
};
diff --git a/bin/templates/cordova/lib/device.js b/bin/templates/cordova/lib/device.js
index 6be55e3..6430d73 100644
--- a/bin/templates/cordova/lib/device.js
+++ b/bin/templates/cordova/lib/device.js
@@ -28,23 +28,43 @@
/**
* Returns a promise for the list of the device ID's found
+ * @param lookHarder When true, try restarting adb if no devices are found.
*/
-module.exports.list = function() {
- return exec('adb devices')
- .then(function(output) {
- var response = output.split('\n');
- var device_list = [];
- for (var i = 1; i < response.length; i++) {
- if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) {
- device_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
+module.exports.list = function(lookHarder) {
+ function helper() {
+ return exec('adb devices')
+ .then(function(output) {
+ var response = output.split('\n');
+ var device_list = [];
+ for (var i = 1; i < response.length; i++) {
+ if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) {
+ device_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
+ }
}
+ return device_list;
+ });
+ }
+ return helper()
+ .then(function(list) {
+ if (list.length === 0 && lookHarder) {
+ // adb kill-server doesn't seem to do the trick.
+ // Could probably find a x-platform version of killall, but I'm not actually
+ // sure that this scenario even happens on non-OSX machines.
+ return exec('killall adb')
+ .then(function() {
+ console.log('Restarting adb to see if more devices are detected.');
+ return helper();
+ }, function() {
+ // For non-killall OS's.
+ return list;
+ });
}
- return device_list;
+ return list;
});
}
module.exports.resolveTarget = function(target) {
- return this.list()
+ return this.list(true)
.then(function(device_list) {
if (!device_list || !device_list.length) {
return Q.reject('ERROR: Failed to deploy to device, no devices found.');