Compare commits

...

4 Commits

Author SHA1 Message Date
d5d1b59b68 Log server pushed
Now that "adb push" stdout is disabled, add a log to notify server
pushed.
2021-11-20 00:02:30 +01:00
d921e2d7a3 Use inherit flags for adb commands
Explicitly indicate, for each call, if stdout and stderr must be
inherited.
2021-11-20 00:02:30 +01:00
4156771077 Expose inherit flag for process execution
Let the caller decide if stdout and stderr must be inherited on process
creation, i.e. if stdout and stderr of the child process should be
printed in the scrcpy console.

This allows to get output and errors for specific adb commands depending
on the context.
2021-11-20 00:02:30 +01:00
c96dc6d2c4 Simplify Windows process inheritance configuration
Merge if-blocks together.
2021-11-19 22:27:01 +01:00
9 changed files with 129 additions and 74 deletions

View File

@ -112,7 +112,7 @@ show_adb_err_msg(enum sc_process_result err, const char *const argv[]) {
static sc_pid
adb_execute_p(const char *serial, const char *const adb_cmd[],
size_t len, sc_pipe *pout) {
size_t len, unsigned inherit, sc_pipe *pout) {
int i;
sc_pid pid;
@ -133,7 +133,7 @@ adb_execute_p(const char *serial, const char *const adb_cmd[],
memcpy(&argv[i], adb_cmd, len * sizeof(const char *));
argv[len + i] = NULL;
enum sc_process_result r =
sc_process_execute_p(argv, &pid, NULL, pout, NULL);
sc_process_execute_p(argv, &pid, inherit, NULL, pout, NULL);
if (r != SC_PROCESS_SUCCESS) {
show_adb_err_msg(r, argv);
pid = SC_PROCESS_NONE;
@ -144,50 +144,54 @@ adb_execute_p(const char *serial, const char *const adb_cmd[],
}
sc_pid
adb_execute(const char *serial, const char *const adb_cmd[], size_t len) {
return adb_execute_p(serial, adb_cmd, len, NULL);
adb_execute(const char *serial, const char *const adb_cmd[], size_t len,
unsigned inherit) {
return adb_execute_p(serial, adb_cmd, len, inherit, NULL);
}
static sc_pid
adb_exec_forward(const char *serial, uint16_t local_port,
const char *device_socket_name) {
const char *device_socket_name, unsigned inherit) {
char local[4 + 5 + 1]; // tcp:PORT
char remote[108 + 14 + 1]; // localabstract:NAME
sprintf(local, "tcp:%" PRIu16, local_port);
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
const char *const adb_cmd[] = {"forward", local, remote};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
}
static sc_pid
adb_exec_forward_remove(const char *serial, uint16_t local_port) {
adb_exec_forward_remove(const char *serial, uint16_t local_port,
unsigned inherit) {
char local[4 + 5 + 1]; // tcp:PORT
sprintf(local, "tcp:%" PRIu16, local_port);
const char *const adb_cmd[] = {"forward", "--remove", local};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
}
static sc_pid
adb_exec_reverse(const char *serial, const char *device_socket_name,
uint16_t local_port) {
uint16_t local_port, unsigned inherit) {
char local[4 + 5 + 1]; // tcp:PORT
char remote[108 + 14 + 1]; // localabstract:NAME
sprintf(local, "tcp:%" PRIu16, local_port);
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
const char *const adb_cmd[] = {"reverse", remote, local};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
}
static sc_pid
adb_exec_reverse_remove(const char *serial, const char *device_socket_name) {
adb_exec_reverse_remove(const char *serial, const char *device_socket_name,
unsigned inherit) {
char remote[108 + 14 + 1]; // localabstract:NAME
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
const char *const adb_cmd[] = {"reverse", "--remove", remote};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
}
static sc_pid
adb_exec_push(const char *serial, const char *local, const char *remote) {
adb_exec_push(const char *serial, const char *local, const char *remote,
unsigned inherit) {
#ifdef __WINDOWS__
// Windows will parse the string, so the paths must be quoted
// (see sys/win/command.c)
@ -203,7 +207,7 @@ adb_exec_push(const char *serial, const char *local, const char *remote) {
#endif
const char *const adb_cmd[] = {"push", local, remote};
sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
#ifdef __WINDOWS__
free((void *) remote);
@ -214,7 +218,7 @@ adb_exec_push(const char *serial, const char *local, const char *remote) {
}
static sc_pid
adb_exec_install(const char *serial, const char *local) {
adb_exec_install(const char *serial, const char *local, unsigned inherit) {
#ifdef __WINDOWS__
// Windows will parse the string, so the local name must be quoted
// (see sys/win/command.c)
@ -225,7 +229,7 @@ adb_exec_install(const char *serial, const char *local) {
#endif
const char *const adb_cmd[] = {"install", "-r", local};
sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
#ifdef __WINDOWS__
free((void *) local);
@ -235,58 +239,62 @@ adb_exec_install(const char *serial, const char *local) {
}
static sc_pid
adb_exec_get_serialno(sc_pipe *pout) {
adb_exec_get_serialno(unsigned inherit, sc_pipe *pout) {
const char *const adb_cmd[] = {"get-serialno"};
return adb_execute_p(NULL, adb_cmd, ARRAY_LEN(adb_cmd), pout);
return adb_execute_p(NULL, adb_cmd, ARRAY_LEN(adb_cmd), inherit, pout);
}
bool
adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port,
const char *device_socket_name) {
sc_pid pid = adb_exec_forward(serial, local_port, device_socket_name);
const char *device_socket_name, unsigned inherit) {
sc_pid pid =
adb_exec_forward(serial, local_port, device_socket_name, inherit);
return sc_process_check_success_intr(intr, pid, "adb forward", true);
}
bool
adb_forward_remove(struct sc_intr *intr, const char *serial,
uint16_t local_port) {
sc_pid pid = adb_exec_forward_remove(serial, local_port);
uint16_t local_port, unsigned inherit) {
sc_pid pid = adb_exec_forward_remove(serial, local_port, inherit);
return sc_process_check_success_intr(intr, pid, "adb forward --remove",
true);
}
bool
adb_reverse(struct sc_intr *intr, const char *serial,
const char *device_socket_name, uint16_t local_port) {
sc_pid pid = adb_exec_reverse(serial, device_socket_name, local_port);
const char *device_socket_name, uint16_t local_port,
unsigned inherit) {
sc_pid pid =
adb_exec_reverse(serial, device_socket_name, local_port, inherit);
return sc_process_check_success_intr(intr, pid, "adb reverse", true);
}
bool
adb_reverse_remove(struct sc_intr *intr, const char *serial,
const char *device_socket_name) {
sc_pid pid = adb_exec_reverse_remove(serial, device_socket_name);
const char *device_socket_name, unsigned inherit) {
sc_pid pid = adb_exec_reverse_remove(serial, device_socket_name, inherit);
return sc_process_check_success_intr(intr, pid, "adb reverse --remove",
true);
}
bool
adb_push(struct sc_intr *intr, const char *serial, const char *local,
const char *remote) {
sc_pid pid = adb_exec_push(serial, local, remote);
const char *remote, unsigned inherit) {
sc_pid pid = adb_exec_push(serial, local, remote, inherit);
return sc_process_check_success_intr(intr, pid, "adb push", true);
}
bool
adb_install(struct sc_intr *intr, const char *serial, const char *local) {
sc_pid pid = adb_exec_install(serial, local);
adb_install(struct sc_intr *intr, const char *serial, const char *local,
unsigned inherit) {
sc_pid pid = adb_exec_install(serial, local, inherit);
return sc_process_check_success_intr(intr, pid, "adb install", true);
}
char *
adb_get_serialno(struct sc_intr *intr) {
adb_get_serialno(struct sc_intr *intr, unsigned inherit) {
sc_pipe pout;
sc_pid pid = adb_exec_get_serialno(&pout);
sc_pid pid = adb_exec_get_serialno(inherit, &pout);
if (pid == SC_PROCESS_NONE) {
LOGE("Could not execute \"adb get-serialno\"");
return NULL;

View File

@ -9,30 +9,33 @@
#include "util/intr.h"
sc_pid
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
adb_execute(const char *serial, const char *const adb_cmd[], size_t len,
unsigned inherit);
bool
adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port,
const char *device_socket_name);
const char *device_socket_name, unsigned inherit);
bool
adb_forward_remove(struct sc_intr *intr, const char *serial,
uint16_t local_port);
uint16_t local_port, unsigned inherit);
bool
adb_reverse(struct sc_intr *intr, const char *serial,
const char *device_socket_name, uint16_t local_port);
const char *device_socket_name, uint16_t local_port,
unsigned inherit);
bool
adb_reverse_remove(struct sc_intr *intr, const char *serial,
const char *device_socket_name);
const char *device_socket_name, unsigned inherit);
bool
adb_push(struct sc_intr *intr, const char *serial, const char *local,
const char *remote);
const char *remote, unsigned inherit);
bool
adb_install(struct sc_intr *intr, const char *serial, const char *local);
adb_install(struct sc_intr *intr, const char *serial, const char *local,
unsigned inherit);
/**
* Execute `adb get-serialno`
@ -40,6 +43,6 @@ adb_install(struct sc_intr *intr, const char *serial, const char *local);
* Return the result, to be freed by the caller, or NULL on error.
*/
char *
adb_get_serialno(struct sc_intr *intr);
adb_get_serialno(struct sc_intr *intr, unsigned inherit);
#endif

View File

@ -20,7 +20,7 @@ enable_tunnel_reverse_any_port(struct sc_adb_tunnel *tunnel,
struct sc_port_range port_range) {
uint16_t port = port_range.first;
for (;;) {
if (!adb_reverse(intr, serial, SC_SOCKET_NAME, port)) {
if (!adb_reverse(intr, serial, SC_SOCKET_NAME, port, SC_STDERR)) {
// the command itself failed, it will fail on any port
return false;
}
@ -51,7 +51,7 @@ enable_tunnel_reverse_any_port(struct sc_adb_tunnel *tunnel,
}
// failure, disable tunnel and try another port
if (!adb_reverse_remove(intr, serial, SC_SOCKET_NAME)) {
if (!adb_reverse_remove(intr, serial, SC_SOCKET_NAME, SC_STDERR)) {
LOGW("Could not remove reverse tunnel on port %" PRIu16, port);
}
@ -81,7 +81,7 @@ enable_tunnel_forward_any_port(struct sc_adb_tunnel *tunnel,
uint16_t port = port_range.first;
for (;;) {
if (adb_forward(intr, serial, port, SC_SOCKET_NAME)) {
if (adb_forward(intr, serial, port, SC_SOCKET_NAME, SC_STDERR)) {
// success
tunnel->local_port = port;
tunnel->enabled = true;
@ -146,9 +146,9 @@ sc_adb_tunnel_close(struct sc_adb_tunnel *tunnel, struct sc_intr *intr,
bool ret;
if (tunnel->forward) {
ret = adb_forward_remove(intr, serial, tunnel->local_port);
ret = adb_forward_remove(intr, serial, tunnel->local_port, SC_STDERR);
} else {
ret = adb_reverse_remove(intr, serial, SC_SOCKET_NAME);
ret = adb_reverse_remove(intr, serial, SC_SOCKET_NAME, SC_STDERR);
assert(tunnel->server_socket != SC_SOCKET_NONE);
if (!net_close(tunnel->server_socket)) {

View File

@ -128,7 +128,8 @@ run_file_handler(void *data) {
if (req.action == ACTION_INSTALL_APK) {
LOGI("Installing %s...", req.file);
bool ok = adb_install(intr, serial, req.file);
bool ok =
adb_install(intr, serial, req.file, SC_STDOUT | SC_STDERR);
if (ok) {
LOGI("%s successfully installed", req.file);
} else {
@ -136,7 +137,8 @@ run_file_handler(void *data) {
}
} else {
LOGI("Pushing %s...", req.file);
bool ok = adb_push(intr, serial, req.file, push_target);
bool ok = adb_push(intr, serial, req.file, push_target,
SC_STDOUT | SC_STDERR);
if (ok) {
LOGI("%s successfully pushed to %s", req.file, push_target);
} else {

View File

@ -112,7 +112,8 @@ push_server(struct sc_intr *intr, const char *serial) {
free(server_path);
return false;
}
bool ok = adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH);
bool ok = adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH,
SC_STDERR);
free(server_path);
return ok;
}
@ -198,7 +199,8 @@ execute_server(struct sc_server *server,
// Port: 5005
// Then click on "Debug"
#endif
return adb_execute(serial, cmd, ARRAY_LEN(cmd));
// Inherit both stdout and stderr (all server logs are printed to stdout)
return adb_execute(serial, cmd, ARRAY_LEN(cmd), SC_STDOUT | SC_STDERR);
}
static bool
@ -430,7 +432,7 @@ sc_server_fill_serial(struct sc_server *server) {
// device/emulator" error)
if (!server->params.serial) {
// The serial is owned by sc_server_params, and will be freed on destroy
server->params.serial = adb_get_serialno(&server->intr);
server->params.serial = adb_get_serialno(&server->intr, SC_STDERR);
if (!server->params.serial) {
LOGE("Could not get device serial");
return false;
@ -457,6 +459,8 @@ run_server(void *data) {
goto error_connection_failed;
}
LOGI("Server pushed");
ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, params->serial,
params->port_range, params->force_adb_forward);
if (!ok) {

View File

@ -11,8 +11,16 @@
#include "util/log.h"
enum sc_process_result
sc_process_execute_p(const char *const argv[], sc_pid *pid,
sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit,
int *pin, int *pout, int *perr) {
bool inherit_stdout = inherit & SC_STDOUT;
bool inherit_stderr = inherit & SC_STDERR;
// If pout is defined, then inherit MUST NOT contain SC_STDOUT.
assert(!pout || !inherit_stdout);
// If perr is defined, then inherit MUST NOT contain SC_STDERR.
assert(!perr || !inherit_stderr);
int in[2];
int out[2];
int err[2];
@ -90,20 +98,31 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid,
}
close(in[1]);
}
// Do not close stdin in the child process, this makes adb fail on
// Linux
if (pout) {
if (out[1] != STDOUT_FILENO) {
dup2(out[1], STDOUT_FILENO);
close(out[1]);
}
close(out[0]);
} else if (!inherit_stdout) {
// Close stdout in the child process
close(STDOUT_FILENO);
}
if (perr) {
if (err[1] != STDERR_FILENO) {
dup2(err[1], STDERR_FILENO);
close(err[1]);
}
close(err[0]);
} else if (!inherit_stderr) {
// Close stderr in the child process
close(STDERR_FILENO);
}
close(internal[0]);
enum sc_process_result err;
if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) {

View File

@ -27,12 +27,22 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
}
enum sc_process_result
sc_process_execute_p(const char *const argv[], HANDLE *handle,
sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit,
HANDLE *pin, HANDLE *pout, HANDLE *perr) {
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
bool inherit_stdout = inherit & SC_STDOUT;
bool inherit_stderr = inherit & SC_STDERR;
// If pout is defined, then inherit MUST NOT contain SC_STDOUT.
assert(!pout || !inherit_stdout);
// If perr is defined, then inherit MUST NOT contain SC_STDERR.
assert(!perr || !inherit_stderr);
// Add 1 per non-NULL pointer
unsigned handle_count = !!pin + !!pout + !!perr;
unsigned handle_count = !!pin
+ (pout || inherit_stdout)
+ (perr || inherit_stderr);
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -80,16 +90,25 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
HANDLE handles[3];
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
// Must be set even if handle_count == 0, so that stdin, stdout and stderr
// are NOT inherited in that case
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
if (handle_count) {
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
unsigned i = 0;
if (pin) {
si.StartupInfo.hStdInput = stdin_read_handle;
handles[i++] = si.StartupInfo.hStdInput;
}
if (pout) {
si.StartupInfo.hStdOutput = stdout_write_handle;
if (pout || inherit_stdout) {
si.StartupInfo.hStdOutput = pout ? stdout_write_handle
: GetStdHandle(STD_OUTPUT_HANDLE);
handles[i++] = si.StartupInfo.hStdOutput;
}
if (perr) {
si.StartupInfo.hStdError = stderr_write_handle;
if (perr || inherit_stderr) {
si.StartupInfo.hStdError = perr ? stderr_write_handle
: GetStdHandle(STD_ERROR_HANDLE);
handles[i++] = si.StartupInfo.hStdError;
}
SIZE_T size;
@ -112,17 +131,6 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
goto error_close_stderr;
}
// Explicitly pass the HANDLEs that must be inherited
unsigned i = 0;
if (pin) {
handles[i++] = stdin_read_handle;
}
if (pout) {
handles[i++] = stdout_write_handle;
}
if (perr) {
handles[i++] = stderr_write_handle;
}
ok = UpdateProcThreadAttribute(lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
handles, handle_count * sizeof(HANDLE),

View File

@ -5,8 +5,8 @@
#include "log.h"
enum sc_process_result
sc_process_execute(const char *const argv[], sc_pid *pid) {
return sc_process_execute_p(argv, pid, NULL, NULL, NULL);
sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit) {
return sc_process_execute_p(argv, pid, inherit, NULL, NULL, NULL);
}
bool

View File

@ -67,20 +67,31 @@ enum sc_process_result {
SC_PROCESS_ERROR_MISSING_BINARY,
};
#define SC_STDOUT (1 << 0)
#define SC_STDERR (1 << 1)
/**
* Execute the command and write the process id to `pid`
*
* The parameter `inherit` is a OR of any of SC_STDOUT and SC_STDERR. It
* indicates if stdout and stderr must be inherited from the scrcpy process (in
* other words, if the process must output to the scrcpy console).
*/
enum sc_process_result
sc_process_execute(const char *const argv[], sc_pid *pid);
sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit);
/**
* Execute the command and write the process id to `pid`
*
* If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr
* (`perr`).
*
* The parameter `inherit` has the same semantics as in `sc_process_execute()`.
* If `pout` is not NULL, then `inherit` MUST NOT contain SC_STDOUT.
* If `perr` is not NULL, then `inherit` MUST NOT contain SC_STDERR.
*/
enum sc_process_result
sc_process_execute_p(const char *const argv[], sc_pid *pid,
sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit,
sc_pipe *pin, sc_pipe *pout, sc_pipe *perr);
/**