char *find_item(const char *item, const char *product) { char *dir; const char *fn; char path[PATH_MAX + 128]; if(!strcmp(item,"boot")) { fn = "boot.img"; } else if(!strcmp(item,"recovery")) { fn = "recovery.img"; } else if(!strcmp(item,"system")) { fn = "system.img"; } else if(!strcmp(item,"vendor")) { fn = "vendor.img"; } else if(!strcmp(item,"userdata")) { fn = "userdata.img"; } else if(!strcmp(item,"cache")) { fn = "cache.img"; } else if(!strcmp(item,"info")) { fn = "android-info.txt"; } else { fprintf(stderr,"unknown partition '%s'\n", item); return 0; } if(product) { get_my_path(path); sprintf(path + strlen(path), "../../../target/product/%s/%s", product, fn); return strdup(path); } dir = getenv("ANDROID_PRODUCT_OUT"); if((dir == 0) || (dir[0] == 0)) { die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); return 0; } sprintf(path, "%s/%s", dir, fn); return strdup(path); }
static char *find_top(char path_buf[PATH_MAX]) { char *top = getenv("ANDROID_BUILD_TOP"); if (top != NULL && top[0] != '\0') { if (!top_works(top)) { fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top); return NULL; } } else { top = getenv("TOP"); if (top != NULL && top[0] != '\0') { if (!top_works(top)) { fprintf(stderr, "adb: bad TOP value \"%s\"\n", top); return NULL; } } else { top = NULL; } } if (top != NULL) { /* The environment pointed to a top directory that works. */ strcpy(path_buf, top); return path_buf; } /* The environment didn't help. Walk up the tree from the CWD * to see if we can find the top. */ char dir[PATH_MAX]; top = find_top_from(getcwd(dir, sizeof(dir)), path_buf); if (top == NULL) { /* If the CWD isn't under a good-looking top, see if the * executable is. */ get_my_path(dir, PATH_MAX); top = find_top_from(dir, path_buf); } return top; }
int launch_server(int server_port) { #ifdef HAVE_WIN32_PROC /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; char program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); startup.hStdOutput = pipe_write; startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ GetModuleFileName( NULL, program_path, sizeof(program_path) ); ret = CreateProcess( program_path, /* program path */ "adb fork-server server", /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #elif defined(HAVE_FORKEXEC) char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork // redirect stderr to the pipe // we use stderr instead of stdout due to stdout's buffering behavior. adb_close(fd[0]); dup2(fd[1], STDERR_FILENO); adb_close(fd[1]); // child process int result = execl(path, "adb", "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #else #error "cannot implement background server start on this platform" #endif return 0; }
int launch_server(int server_port) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; HANDLE stdout_handle, stderr_handle; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; char program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). */ stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); if (stdout_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); } if (stderr_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 ); } ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); startup.hStdOutput = pipe_write; startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ GetModuleFileName( NULL, program_path, sizeof(program_path) ); char args[64]; snprintf(args, sizeof(args), "adb -P %d fork-server server", server_port); ret = CreateProcess( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #else /* !defined(_WIN32) */ char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork // redirect stderr to the pipe // we use stderr instead of stdout due to stdout's buffering behavior. adb_close(fd[0]); dup2(fd[1], STDERR_FILENO); adb_close(fd[1]); char str_port[30]; snprintf(str_port, sizeof(str_port), "%d", server_port); // child process int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #endif /* !defined(_WIN32) */ return 0; }
int launch_server(int server_port) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE nul_read, nul_write; HANDLE pipe_read, pipe_write; HANDLE stdout_handle, stderr_handle; SECURITY_ATTRIBUTES sa; STARTUPINFOW startup; PROCESS_INFORMATION pinfo; WCHAR program_path[ MAX_PATH ]; int ret; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Redirect stdin and stderr to Windows /dev/null. If we instead pass our * stdin/stderr handles and they are console handles, when the adb server * starts up, the C Runtime will see console handles for a process that * isn't connected to a console and it will configure stderr to be closed. * At that point, freopen() could be used to reopen stderr, but it would * take more massaging to fixup the file descriptor number that freopen() * uses. It's simplest to avoid all of this complexity by just redirecting * stdin/stderr to `nul' and then the C Runtime acts as expected. */ nul_read = CreateFileW(L"nul", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_read == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFileW(nul, GENERIC_READ) failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } nul_write = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_write == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFileW(nul, GENERIC_WRITE) failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle(nul_read); return -1; } /* create pipe, and ensure its read handle isn't inheritable */ ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); if (!ret) { fprintf(stderr, "CreatePipe() failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle(nul_read); CloseHandle(nul_write); return -1; } SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). */ stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); if (stdout_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); } if (stderr_handle != INVALID_HANDLE_VALUE) { SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 ); } ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = nul_read; startup.hStdOutput = pipe_write; startup.hStdError = nul_write; startup.dwFlags = STARTF_USESTDHANDLES; ZeroMemory( &pinfo, sizeof(pinfo) ); /* get path of current program */ DWORD module_result = GetModuleFileNameW(NULL, program_path, arraysize(program_path)); if ((module_result == arraysize(program_path)) || (module_result == 0)) { // String truncation or some other error. fprintf(stderr, "GetModuleFileNameW() failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } WCHAR args[64]; snwprintf(args, arraysize(args), L"adb -P %d fork-server server", server_port); ret = CreateProcessW( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo ); CloseHandle( nul_read ); CloseHandle( nul_write ); CloseHandle( pipe_write ); if (!ret) { fprintf(stderr, "CreateProcess failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); CloseHandle( pipe_read ); return -1; } CloseHandle( pinfo.hProcess ); CloseHandle( pinfo.hThread ); /* wait for the "OK\n" message */ { char temp[3]; DWORD count; ret = ReadFile( pipe_read, temp, 3, &count, NULL ); CloseHandle( pipe_read ); if ( !ret ) { fprintf(stderr, "could not read ok from ADB Server, error: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } } #else /* !defined(_WIN32) */ char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and the child will write on fd[1] if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork adb_close(fd[0]); char str_port[30]; snprintf(str_port, sizeof(str_port), "%d", server_port); char reply_fd[30]; snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]); // child process int result = execl(path, "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #endif /* !defined(_WIN32) */ return 0; }
int launch_server(int server_port) { #if defined(_WIN32) /* we need to start the server in the background */ /* we create a PIPE that will be used to wait for the server's "OK" */ /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Redirect stdin to Windows /dev/null. If we instead pass an original // stdin/stdout/stderr handle and it is a console handle, when the adb // server starts up, the C Runtime will see a console handle for a process // that isn't connected to a console and it will configure // stdin/stdout/stderr to be closed. At that point, freopen() could be used // to reopen stderr/out, but it would take more massaging to fixup the file // descriptor number that freopen() uses. It's simplest to avoid all of this // complexity by just redirecting stdin to `nul' and then the C Runtime acts // as expected. unique_handle nul_read(CreateFileW(L"nul", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); if (nul_read.get() == INVALID_HANDLE_VALUE) { fprintf(stderr, "Cannot open 'nul': %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } // create pipes with non-inheritable read handle, inheritable write handle unique_handle ack_read, ack_write; if (!_create_anonymous_pipe(&ack_read, &ack_write, &sa)) { return -1; } unique_handle stdout_read, stdout_write; if (!_create_anonymous_pipe(&stdout_read, &stdout_write, &sa)) { return -1; } unique_handle stderr_read, stderr_write; if (!_create_anonymous_pipe(&stderr_read, &stderr_write, &sa)) { return -1; } /* Some programs want to launch an adb command and collect its output by * calling CreateProcess with inheritable stdout/stderr handles, then * using read() to get its output. When this happens, the stdout/stderr * handles passed to the adb client process will also be inheritable. * When starting the adb server here, care must be taken to reset them * to non-inheritable. * Otherwise, something bad happens: even if the adb command completes, * the calling process is stuck while read()-ing from the stdout/stderr * descriptors, because they're connected to corresponding handles in the * adb server process (even if the latter never uses/writes to them). * Note that even if we don't pass these handles in the STARTUPINFO struct, * if they're marked inheritable, they're still inherited, requiring us to * deal with this. * * If we're still having problems with inheriting random handles in the * future, consider using PROC_THREAD_ATTRIBUTE_HANDLE_LIST to explicitly * specify which handles should be inherited: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/16/10248328.aspx */ if (!_make_handle_noninheritable(GetStdHandle(STD_INPUT_HANDLE))) { return -1; } if (!_make_handle_noninheritable(GetStdHandle(STD_OUTPUT_HANDLE))) { return -1; } if (!_make_handle_noninheritable(GetStdHandle(STD_ERROR_HANDLE))) { return -1; } STARTUPINFOW startup; ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = nul_read.get(); startup.hStdOutput = stdout_write.get(); startup.hStdError = stderr_write.get(); startup.dwFlags = STARTF_USESTDHANDLES; // Verify that the pipe_write handle value can be passed on the command line // as %d and that the rest of adb code can pass it around in an int. const int ack_write_as_int = cast_handle_to_int(ack_write.get()); if (cast_int_to_handle(ack_write_as_int) != ack_write.get()) { // If this fires, either handle values are larger than 32-bits or else // there is a bug in our casting. // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx fprintf(stderr, "Cannot fit pipe handle value into 32-bits: 0x%p\n", ack_write.get()); return -1; } // get path of current program WCHAR program_path[MAX_PATH]; const DWORD module_result = GetModuleFileNameW(NULL, program_path, arraysize(program_path)); if ((module_result >= arraysize(program_path)) || (module_result == 0)) { // String truncation or some other error. fprintf(stderr, "Cannot get executable path: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } WCHAR args[64]; snwprintf(args, arraysize(args), L"adb -P %d fork-server server --reply-fd %d", server_port, ack_write_as_int); PROCESS_INFORMATION pinfo; ZeroMemory(&pinfo, sizeof(pinfo)); if (!CreateProcessW( program_path, /* program path */ args, /* the fork-server argument will set the debug = 2 in the child */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ DETACHED_PROCESS, /* the new process doesn't have a console */ NULL, /* use parent's environment block */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo )) { fprintf(stderr, "Cannot create process: %s\n", SystemErrorCodeToString(GetLastError()).c_str()); return -1; } unique_handle process_handle(pinfo.hProcess); pinfo.hProcess = NULL; // Close handles that we no longer need to complete the rest. CloseHandle(pinfo.hThread); pinfo.hThread = NULL; nul_read.reset(); ack_write.reset(); stdout_write.reset(); stderr_write.reset(); // Start threads to read from subprocess stdout/stderr and write to ours // to make subprocess errors easier to diagnose. // In the past, reading from a pipe before the child process's C Runtime // started up and called GetFileType() caused a hang: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/02/10243553.aspx#10244216 // This is reportedly fixed in Windows Vista: https://support.microsoft.com/en-us/kb/2009703 // I was unable to reproduce the problem on Windows XP. It sounds like a // Windows Update may have fixed this: https://www.duckware.com/tech/peeknamedpipe.html unique_handle stdout_thread(reinterpret_cast<HANDLE>( _beginthreadex(NULL, 0, _redirect_stdout_thread, stdout_read.get(), 0, NULL))); if (stdout_thread.get() == nullptr) { fprintf(stderr, "Cannot create thread: %s\n", strerror(errno)); return -1; } stdout_read.release(); // Transfer ownership to new thread unique_handle stderr_thread(reinterpret_cast<HANDLE>( _beginthreadex(NULL, 0, _redirect_stderr_thread, stderr_read.get(), 0, NULL))); if (stderr_thread.get() == nullptr) { fprintf(stderr, "Cannot create thread: %s\n", strerror(errno)); return -1; } stderr_read.release(); // Transfer ownership to new thread bool got_ack = false; // Wait for the "OK\n" message, for the pipe to be closed, or other error. { char temp[3]; DWORD count = 0; if (ReadFile(ack_read.get(), temp, sizeof(temp), &count, NULL)) { const CHAR expected[] = "OK\n"; const DWORD expected_length = arraysize(expected) - 1; if (count == expected_length && memcmp(temp, expected, expected_length) == 0) { got_ack = true; } else { fprintf(stderr, "ADB server didn't ACK\n"); } } else { const DWORD err = GetLastError(); // If the ACK was not written and the process exited, GetLastError() // is probably ERROR_BROKEN_PIPE, in which case that info is not // useful to the user. fprintf(stderr, "could not read ok from ADB Server%s\n", err == ERROR_BROKEN_PIPE ? "" : android::base::StringPrintf(": %s", SystemErrorCodeToString(err).c_str()).c_str()); } } // Always try to wait a bit for threads reading stdout/stderr to finish. // If the process started ok, it should close the pipes causing the threads // to finish. If the process had an error, it should exit, also causing // the pipes to be closed. In that case we want to read all of the output // and write it out so that the user can diagnose failures. const DWORD thread_timeout_ms = 15 * 1000; const HANDLE threads[] = { stdout_thread.get(), stderr_thread.get() }; const DWORD wait_result = WaitForMultipleObjects(arraysize(threads), threads, TRUE, thread_timeout_ms); if (wait_result == WAIT_TIMEOUT) { // Threads did not finish after waiting a little while. Perhaps the // server didn't close pipes, or it is hung. fprintf(stderr, "Timed-out waiting for threads to finish reading from " "ADB Server\n"); // Process handles are signaled when the process exits, so if we wait // on the handle for 0 seconds and it returns 'timeout', that means that // the process is still running. if (WaitForSingleObject(process_handle.get(), 0) == WAIT_TIMEOUT) { // We could TerminateProcess(), but that seems somewhat presumptive. fprintf(stderr, "ADB Server is running: process id %lu\n", pinfo.dwProcessId); } return -1; } if (wait_result != WAIT_OBJECT_0) { fprintf(stderr, "Unexpected result waiting for threads: %lu: %s\n", wait_result, SystemErrorCodeToString(GetLastError()).c_str()); return -1; } // For now ignore the thread exit codes and assume they worked properly. if (!got_ack) { return -1; } #else /* !defined(_WIN32) */ char path[PATH_MAX]; int fd[2]; // set up a pipe so the child can tell us when it is ready. // fd[0] will be parent's end, and the child will write on fd[1] if (pipe(fd)) { fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); return -1; } get_my_path(path, PATH_MAX); pid_t pid = fork(); if(pid < 0) return -1; if (pid == 0) { // child side of the fork adb_close(fd[0]); char str_port[30]; snprintf(str_port, sizeof(str_port), "%d", server_port); char reply_fd[30]; snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]); // child process int result = execl(path, "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { // parent side of the fork char temp[3]; temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; // wait for the "OK\n" message adb_close(fd[1]); int ret = adb_read(fd[0], temp, 3); int saved_errno = errno; adb_close(fd[0]); if (ret < 0) { fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno); return -1; } if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { fprintf(stderr, "ADB server didn't ACK\n" ); return -1; } setsid(); } #endif /* !defined(_WIN32) */ return 0; }