Merge changes I6a842960,If618c26b am: 7920502065
am: c08a536a32

Change-Id: I29c44864fb1a955d3f2e07deb8bc970ee6c3faaf
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index c818fca..44d3276 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -113,16 +113,12 @@
     asocket* s = create_local_socket(arg->socket_fd);
     ASSERT_TRUE(s != nullptr);
     arg->bytes_written = 0;
-    while (true) {
-        std::string data;
-        data.resize(MAX_PAYLOAD);
-        arg->bytes_written += data.size();
-        int ret = s->enqueue(s, std::move(data));
-        if (ret == 1) {
-            // The writer has one packet waiting to send.
-            break;
-        }
-    }
+
+    std::string data;
+    data.resize(MAX_PAYLOAD);
+    arg->bytes_written += data.size();
+    int ret = s->enqueue(s, std::move(data));
+    ASSERT_EQ(1, ret);
 
     asocket* cause_close_s = create_local_socket(arg->cause_close_fd);
     ASSERT_TRUE(cause_close_s != nullptr);
@@ -233,15 +229,16 @@
     PrepareThread();
     std::thread thread(fdevent_loop);
 
-    ASSERT_TRUE(WriteFdExactly(head_fd[0], "foo", 3));
-    ASSERT_EQ(0, adb_shutdown(head_fd[0], SHUT_RD));
-    const char* str = "write succeeds, but local_socket will fail to write";
-    ASSERT_TRUE(WriteFdExactly(tail_fd[0], str, strlen(str)));
-    ASSERT_TRUE(WriteFdExactly(head_fd[0], "bar", 3));
-    char buf[6];
-    ASSERT_TRUE(ReadFdExactly(tail_fd[0], buf, 6));
+    EXPECT_TRUE(WriteFdExactly(head_fd[0], "foo", 3));
 
-    ASSERT_EQ(0, memcmp(buf, "foobar", 6));
+    EXPECT_EQ(0, adb_shutdown(head_fd[0], SHUT_RD));
+    const char* str = "write succeeds, but local_socket will fail to write";
+    EXPECT_TRUE(WriteFdExactly(tail_fd[0], str, strlen(str)));
+    EXPECT_TRUE(WriteFdExactly(head_fd[0], "bar", 3));
+
+    char buf[6];
+    EXPECT_TRUE(ReadFdExactly(tail_fd[0], buf, 6));
+    EXPECT_EQ(0, memcmp(buf, "foobar", 6));
 
     adb_close(head_fd[0]);
     adb_close(tail_fd[0]);
diff --git a/adb/test_device.py b/adb/test_device.py
index 4cf2206..d422df2 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -31,6 +31,7 @@
 import subprocess
 import sys
 import tempfile
+import threading
 import time
 import unittest
 
@@ -493,6 +494,29 @@
         stdout, _ = self.device.shell(["cat", log_path])
         self.assertEqual(stdout.strip(), "SIGHUP")
 
+    def test_exit_stress(self):
+        """Hammer `adb shell exit 42` with multiple threads."""
+        thread_count = 48
+        result = dict()
+        def hammer(thread_idx, thread_count, result):
+            success = True
+            for i in range(thread_idx, 240, thread_count):
+                ret = subprocess.call(['adb', 'shell', 'exit {}'.format(i)])
+                if ret != i % 256:
+                    success = False
+                    break
+            result[thread_idx] = success
+
+        threads = []
+        for i in range(thread_count):
+            thread = threading.Thread(target=hammer, args=(i, thread_count, result))
+            thread.start()
+            threads.append(thread)
+        for thread in threads:
+            thread.join()
+        for i, success in result.iteritems():
+            self.assertTrue(success)
+
 
 class ArgumentEscapingTest(DeviceTest):
     def test_shell_escaping(self):