From 12cd32ce92362a6a43fee83fafc16338d7414683 Mon Sep 17 00:00:00 2001 From: yuchenlin Date: Sat, 1 Sep 2018 09:18:06 +0800 Subject: [PATCH] Notify adb missing There are many user who encounters missing adb. To stop things happens again, we check it and show sexy response to user. Signed-off-by: yuchenlin --- app/src/command.c | 34 +++++++++++++++++++-- app/src/command.h | 2 +- app/src/sys/unix/command.c | 60 +++++++++++++++++++++++++++++++++----- app/src/sys/win/command.c | 11 ++++--- 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/app/src/command.c b/app/src/command.c index b7ea67d23c..4f3e8d491d 100644 --- a/app/src/command.c +++ b/app/src/command.c @@ -1,5 +1,9 @@ #include "command.h" +#ifdef __WINDOWS__ +#else +#include +#endif #include #include #include @@ -18,9 +22,30 @@ static inline const char *get_adb_command() { return adb_command; } +static void show_err_msg(int err) { +#ifdef __WINDOWS__ + LOGE("Failed to execute adb.\n"); +#else + switch (err) { + case 0: + break; + case -1: + LOGE("Failed to execute adb.\n"); + break; + case ENOENT: + LOGE("Missing adb. You need adb, accessible from your PATH to execute scrcpy.\n"); + break; + default: + LOGE("Failed to execute adb, errno: [%d].\n", err); + break; + } +#endif +} + process_t adb_execute(const char *serial, const char *const adb_cmd[], int len) { const char *cmd[len + 4]; - int i; + int i, r; + process_t process; cmd[0] = get_adb_command(); if (serial) { cmd[1] = "-s"; @@ -32,7 +57,12 @@ process_t adb_execute(const char *serial, const char *const adb_cmd[], int len) memcpy(&cmd[i], adb_cmd, len * sizeof(const char *)); cmd[len + i] = NULL; - return cmd_execute(cmd[0], cmd); + r = cmd_execute(cmd[0], cmd, &process); + if (r != 0) { + show_err_msg(r); + return -1; + } + return process; } process_t adb_forward(const char *serial, uint16_t local_port, const char *device_socket_name) { diff --git a/app/src/command.h b/app/src/command.h index 4113f2512b..dfc0d58a33 100644 --- a/app/src/command.h +++ b/app/src/command.h @@ -32,7 +32,7 @@ #endif # define NO_EXIT_CODE -1 -process_t cmd_execute(const char *path, const char *const argv[]); +int cmd_execute(const char *path, const char *const argv[], process_t *process); SDL_bool cmd_terminate(process_t pid); SDL_bool cmd_simple_wait(process_t pid, exit_code_t *exit_code); diff --git a/app/src/sys/unix/command.c b/app/src/sys/unix/command.c index 0083a93b3a..53d0bb1e68 100644 --- a/app/src/sys/unix/command.c +++ b/app/src/sys/unix/command.c @@ -1,5 +1,7 @@ #include "command.h" +#include +#include #include #include #include @@ -7,18 +9,62 @@ #include #include "log.h" -pid_t cmd_execute(const char *path, const char *const argv[]) { - pid_t pid = fork(); - if (pid == -1) { - perror("fork"); +int cmd_execute(const char *path, const char *const argv[], pid_t *pid) { + int fd[2]; + int ret = 0; + + if (0 > pipe(fd)) { + perror("pipe"); return -1; } - if (pid == 0) { + + *pid = fork(); + if (*pid == -1) { + perror("fork"); + ret = -1; + goto END; + } + + if (*pid > 0) { + /* parent close write side. */ + close(fd[1]); + fd[1] = -1; + /* and blocking read until child exec or write some fail + * reason in fd. */ + if (read(fd[0], &ret, sizeof(int)) == -1) { + perror("read"); + ret = -1; + goto END; + } + } else if (*pid == 0) { + /* child close read side. */ + close(fd[0]); + if (fcntl(fd[1], F_SETFD, FD_CLOEXEC) == -1) { + perror("fcntl"); + /* To prevent parent hang in read, we should exit when error. */ + close(fd[1]); + _exit(1); + } execvp(path, (char *const *)argv); - perror("exec"); + /* if child execvp failed, before exit, we should write + * reason into the pipe. */ + ret = errno; + if (write(fd[1], &ret, sizeof(int)) == -1) { + perror("write"); + } + /* close write side before exiting. */ + close(fd[1]); _exit(1); } - return pid; + +END: + if (fd[0] != -1) { + close(fd[0]); + } + if (fd[1] != -1) { + close(fd[1]); + } + return ret; } SDL_bool cmd_terminate(pid_t pid) { diff --git a/app/src/sys/win/command.c b/app/src/sys/win/command.c index 2552eeca4f..cea928b40d 100644 --- a/app/src/sys/win/command.c +++ b/app/src/sys/win/command.c @@ -4,7 +4,7 @@ #include "log.h" #include "str_util.h" -HANDLE cmd_execute(const char *path, const char *const argv[]) { +int cmd_execute(const char *path, const char *const argv[], HANDLE *handle) { STARTUPINFO si; PROCESS_INFORMATION pi; memset(&si, 0, sizeof(si)); @@ -18,7 +18,8 @@ HANDLE cmd_execute(const char *path, const char *const argv[]) { size_t ret = xstrjoin(cmd, argv, ' ', sizeof(cmd)); if (ret >= sizeof(cmd)) { LOGE("Command too long (%" PRIsizet " chars)", sizeof(cmd) - 1); - return NULL; + *handle = NULL; + return -1; } #ifdef WINDOWS_NOCONSOLE @@ -27,10 +28,12 @@ HANDLE cmd_execute(const char *path, const char *const argv[]) { int flags = 0; #endif if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi)) { - return NULL; + *handle = NULL; + return -1; } - return pi.hProcess; + *handle = pi.hProcess; + return 0; } SDL_bool cmd_terminate(HANDLE handle) {