win32: adb start-server shows stdout/stderr output from actual server
When launching the adb server (typically from adb start-server),
redirect stdout/stderr to anonymous pipes which are read by threads in
the parent process, to make error diagnosis easier.
If there is an error during adb start-server, the output looks like:
> adb start-server
* daemon not running. starting it now on port 5037 *
error: could not blah # from server process
could not read ok from ADB Server # from launch_server
* failed to start daemon * # from adb_connect
error: cannot connect to daemon # from adb_commandline
Fix handle-leaks in launch_server by using new unique_handle class
that is based on std::unique_ptr.
In the server, close stdin and redirect to adb.log *before* sending the
ACK, so that any errors are reported early instead of after the ACK.
Change-Id: I943881210a0ea9458fc36851339f916c3d6a0830
Signed-off-by: Spencer Low <CompareAndSwap@gmail.com>
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 39bb02b..f6ddeb4 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -76,6 +76,8 @@
static const char kNullFileName[] = "NUL";
static BOOL WINAPI ctrlc_handler(DWORD type) {
+ // TODO: Consider trying to kill a starting up adb server (if we're in
+ // launch_server) by calling GenerateConsoleCtrlEvent().
exit(STATUS_CONTROL_C_EXIT);
return TRUE;
}
@@ -128,17 +130,26 @@
}
unix_close(fd);
-#ifdef _WIN32
- // On Windows, stderr is buffered by default, so switch to non-buffered
- // to match Linux.
- setvbuf(stderr, NULL, _IONBF, 0);
-#endif
fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
LOG(INFO) << adb_version();
}
int adb_main(int is_daemon, int server_port, int ack_reply_fd) {
#if defined(_WIN32)
+ // adb start-server starts us up with stdout and stderr hooked up to
+ // anonymous pipes to. When the C Runtime sees this, it makes stderr and
+ // stdout buffered, but to improve the chance that error output is seen,
+ // unbuffer stdout and stderr just like if we were run at the console.
+ // This also keeps stderr unbuffered when it is redirected to adb.log.
+ if (is_daemon) {
+ if (setvbuf(stdout, NULL, _IONBF, 0) == -1) {
+ fatal("cannot make stdout unbuffered: %s", strerror(errno));
+ }
+ if (setvbuf(stderr, NULL, _IONBF, 0) == -1) {
+ fatal("cannot make stderr unbuffered: %s", strerror(errno));
+ }
+ }
+
SetConsoleCtrlHandler(ctrlc_handler, TRUE);
#else
signal(SIGPIPE, SIG_IGN);
@@ -162,6 +173,12 @@
// Inform our parent that we are up and running.
if (is_daemon) {
+ close_stdin();
+ setup_daemon_logging();
+
+ // Any error output written to stderr now goes to adb.log. We could
+ // keep around a copy of the stderr fd and use that to write any errors
+ // encountered by the following code, but that is probably overkill.
#if defined(_WIN32)
const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
const CHAR ack[] = "OK\n";
@@ -184,8 +201,6 @@
}
unix_close(ack_reply_fd);
#endif
- close_stdin();
- setup_daemon_logging();
}
D("Event loop starting\n");