Merge "adb: move adb to poll."
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index c508b32..d287480 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -524,6 +524,20 @@
return android::base::StringPrintf("%s:%s", prefix, command);
}
+// Checks whether the device indicated by |transport_type| and |serial| supports
+// |feature|. Returns the response string, which will be empty if the device
+// could not be found or the feature is not supported.
+static std::string CheckFeature(const std::string& feature,
+ TransportType transport_type,
+ const char* serial) {
+ std::string result, error, command("check-feature:" + feature);
+ if (!adb_query(format_host_command(command.c_str(), transport_type, serial),
+ &result, &error)) {
+ return "";
+ }
+ return result;
+}
+
static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
bool show_progress)
{
@@ -783,12 +797,15 @@
wait_for_device("wait-for-device", transport_type, serial);
}
- read_and_dump(fd);
- int rc = adb_close(fd);
- if (rc) {
- perror("close");
+ bool use_shell_protocol = !CheckFeature(kFeatureShell2, transport_type,
+ serial).empty();
+ int exit_code = read_and_dump(fd, use_shell_protocol);
+
+ if (adb_close(fd) < 0) {
+ PLOG(ERROR) << "failure closing FD " << fd;
}
- return rc;
+
+ return exit_code;
}
static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
@@ -1013,20 +1030,6 @@
#endif
}
-// Checks whether the device indicated by |transport_type| and |serial| supports
-// |feature|. Returns the response string, which will be empty if the device
-// could not be found or the feature is not supported.
-static std::string CheckFeature(const std::string& feature,
- TransportType transport_type,
- const char* serial) {
- std::string result, error, command("check-feature:" + feature);
- if (!adb_query(format_host_command(command.c_str(), transport_type, serial),
- &result, &error)) {
- return "";
- }
- return result;
-}
-
int adb_commandline(int argc, const char **argv) {
int no_daemon = 0;
int is_daemon = 0;
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index 0274ae3..f1bc36d 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -413,6 +413,14 @@
D("closing FD %d", dead_sfd->fd());
FD_CLR(dead_sfd->fd(), &master_read_set);
FD_CLR(dead_sfd->fd(), &master_write_set);
+ if (dead_sfd == &protocol_sfd_) {
+ // Using SIGHUP is a decent general way to indicate that the
+ // controlling process is going away. If specific signals are
+ // needed (e.g. SIGINT), pass those through the shell protocol
+ // and only fall back on this for unexpected closures.
+ D("protocol FD died, sending SIGHUP to pid %d", pid_);
+ kill(pid_, SIGHUP);
+ }
dead_sfd->Reset();
}
}
diff --git a/adb/test_device.py b/adb/test_device.py
index fedd2d7..4452eed 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -23,6 +23,7 @@
import random
import shlex
import shutil
+import signal
import subprocess
import tempfile
import unittest
@@ -196,6 +197,34 @@
self.assertEqual('foo' + self.device.linesep, result[1])
self.assertEqual('bar' + self.device.linesep, result[2])
+ def test_non_interactive_sigint(self):
+ """Tests that SIGINT in a non-interactive shell kills the process.
+
+ This requires the shell protocol in order to detect the broken
+ pipe; raw data transfer mode will only see the break once the
+ subprocess tries to read or write.
+
+ Bug: http://b/23825725
+ """
+ if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+ raise unittest.SkipTest('shell protocol unsupported on this device')
+
+ # Start a long-running process.
+ sleep_proc = subprocess.Popen(
+ self.device.adb_cmd + shlex.split('shell echo $$; sleep 60'),
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ remote_pid = sleep_proc.stdout.readline().strip()
+ self.assertIsNone(sleep_proc.returncode, 'subprocess terminated early')
+ proc_query = shlex.split('ps {0} | grep {0}'.format(remote_pid))
+
+ # Verify that the process is running, send signal, verify it stopped.
+ self.device.shell(proc_query)
+ os.kill(sleep_proc.pid, signal.SIGINT)
+ sleep_proc.communicate()
+ self.assertEqual(1, self.device.shell_nocheck(proc_query)[0],
+ 'subprocess failed to terminate')
+
class ArgumentEscapingTest(DeviceTest):
def test_shell_escaping(self):
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
index ca2d260..d0d6772 100755
--- a/crash_reporter/crash_sender
+++ b/crash_reporter/crash_sender
@@ -76,6 +76,9 @@
# Set this to 1 to allow uploading of device coredumps.
DEVCOREDUMP_UPLOAD_FLAG_FILE="${CRASH_STATE_DIR}/device_coredump_upload_allowed"
+# The weave configuration file.
+WEAVE_CONF_FILE="/etc/weaved/weaved.conf"
+
# The syslog tag for all logging we emit.
TAG="$(basename $0)[$$]"
@@ -296,6 +299,7 @@
local version="$(get_key_value "${meta_path}" "upload_var_ver")"
local upload_prefix="$(get_key_value "${meta_path}" "upload_prefix")"
local guid
+ local model_manifest_id="$(get_key_value "${WEAVE_CONF_FILE}" "model_id")"
# If crash_reporter.server is not set return with an error.
if [ -z "${url}" ]; then
@@ -455,6 +459,7 @@
-F "ver=${version}" \
-F "hwclass=${hwclass}" \
-F "exec_name=${exec_name}" \
+ -F "model_manifest_id=${model_manifest_id}" \
${image_type:+-F "image_type=${image_type}"} \
${boot_mode:+-F "boot_mode=${boot_mode}"} \
${error_type:+-F "error_type=${error_type}"} \