adb start-server: Use a separate fd for sending initial OK

When "adb start-server" is issued, and a server needs to be launched,
adb client forks itself and the child process runs the server routine.
Once the server initializes its various components, it sends an "OK\n"
back to the client via its stderror (or stdout on Windows).

This sequence breaks down if before sending the "OK\n", the server
happens to log something on its stderr. In order to avoid this, the
client now expects the ack to come on a different fd rather than one
of the standard streams.

Bug: https://code.google.com/p/android/issues/detail?id=182150

Change-Id: I9d58a08068d71eb3b77e8a7377e934631c016466
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index d7a0c8d..2e182e8 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -954,6 +954,14 @@
     int r;
     TransportType transport_type = kTransportAny;
 
+#if defined(_WIN32)
+    // TODO(compareandswap): Windows should use a separate reply fd too.
+    int ack_reply_fd = STDOUT_FILENO;
+#else
+    int ack_reply_fd = -1;
+#endif
+
+
     // If defined, this should be an absolute path to
     // the directory containing all of the various system images
     // for a particular product.  If not defined, and the adb
@@ -971,7 +979,7 @@
     const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
     int server_port = DEFAULT_ADB_PORT;
     if (server_port_str && strlen(server_port_str) > 0) {
-        server_port = (int) strtol(server_port_str, NULL, 0);
+        server_port = strtol(server_port_str, nullptr, 0);
         if (server_port <= 0 || server_port > 65535) {
             fprintf(stderr,
                     "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
@@ -989,6 +997,16 @@
         } else if (!strcmp(argv[0], "fork-server")) {
             /* this is a special flag used only when the ADB client launches the ADB Server */
             is_daemon = 1;
+        } else if (!strcmp(argv[0], "--reply-fd")) {
+            if (argc < 2) return usage();
+            const char* reply_fd_str = argv[1];
+            argc--;
+            argv++;
+            ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
+            if (ack_reply_fd <= 2) { // Disallow stdin, stdout, and stderr.
+                fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
+                return usage();
+            }
         } else if (!strncmp(argv[0], "-p", 2)) {
             const char* product = nullptr;
             if (argv[0][2] == '\0') {
@@ -1066,7 +1084,11 @@
 
     if (is_server) {
         if (no_daemon || is_daemon) {
-            r = adb_main(is_daemon, server_port);
+            if (ack_reply_fd == -1) {
+                fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
+                return usage();
+            }
+            r = adb_main(is_daemon, server_port, ack_reply_fd);
         } else {
             r = launch_server(server_port);
         }