Compare commits

..

3 Commits

Author SHA1 Message Date
Romain Vimont
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
Romain Vimont
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
Romain Vimont
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
6 changed files with 79 additions and 76 deletions

View File

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

View File

@@ -128,8 +128,8 @@ run_file_handler(void *data) {
if (req.action == ACTION_INSTALL_APK) { if (req.action == ACTION_INSTALL_APK) {
LOGI("Installing %s...", req.file); LOGI("Installing %s...", req.file);
bool ok = adb_install(intr, serial, req.file, bool ok =
SC_INHERIT_STDOUT | SC_INHERIT_STDERR); adb_install(intr, serial, req.file, SC_STDOUT | SC_STDERR);
if (ok) { if (ok) {
LOGI("%s successfully installed", req.file); LOGI("%s successfully installed", req.file);
} else { } else {
@@ -138,7 +138,7 @@ run_file_handler(void *data) {
} else { } else {
LOGI("Pushing %s...", req.file); 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_INHERIT_STDOUT | SC_INHERIT_STDERR); SC_STDOUT | SC_STDERR);
if (ok) { if (ok) {
LOGI("%s successfully pushed to %s", req.file, push_target); LOGI("%s successfully pushed to %s", req.file, push_target);
} else { } else {

View File

@@ -113,7 +113,7 @@ push_server(struct sc_intr *intr, const char *serial) {
return false; 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_INHERIT_STDERR); SC_STDERR);
free(server_path); free(server_path);
return ok; return ok;
} }
@@ -200,8 +200,7 @@ execute_server(struct sc_server *server,
// Then click on "Debug" // Then click on "Debug"
#endif #endif
// Inherit both stdout and stderr (all server logs are printed to stdout) // Inherit both stdout and stderr (all server logs are printed to stdout)
return adb_execute(serial, cmd, ARRAY_LEN(cmd), return adb_execute(serial, cmd, ARRAY_LEN(cmd), SC_STDOUT | SC_STDERR);
SC_INHERIT_STDOUT | SC_INHERIT_STDERR);
} }
static bool static bool
@@ -433,8 +432,7 @@ sc_server_fill_serial(struct sc_server *server) {
// device/emulator" error) // device/emulator" error)
if (!server->params.serial) { if (!server->params.serial) {
// The serial is owned by sc_server_params, and will be freed on destroy // 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);
SC_INHERIT_STDERR);
if (!server->params.serial) { if (!server->params.serial) {
LOGE("Could not get device serial"); LOGE("Could not get device serial");
return false; return false;

View File

@@ -13,12 +13,12 @@
enum sc_process_result enum sc_process_result
sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit, sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit,
int *pin, int *pout, int *perr) { int *pin, int *pout, int *perr) {
bool inherit_stdout = inherit & SC_INHERIT_STDOUT; bool inherit_stdout = inherit & SC_STDOUT;
bool inherit_stderr = inherit & SC_INHERIT_STDERR; bool inherit_stderr = inherit & SC_STDERR;
// If pout is defined, then inherit MUST NOT contain SC_INHERIT_STDOUT. // If pout is defined, then inherit MUST NOT contain SC_STDOUT.
assert(!pout || !inherit_stdout); assert(!pout || !inherit_stdout);
// If perr is defined, then inherit MUST NOT contain SC_INHERIT_STDERR. // If perr is defined, then inherit MUST NOT contain SC_STDERR.
assert(!perr || !inherit_stderr); assert(!perr || !inherit_stderr);
int in[2]; int in[2];

View File

@@ -29,14 +29,19 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
enum sc_process_result enum sc_process_result
sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit, sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit,
HANDLE *pin, HANDLE *pout, HANDLE *perr) { HANDLE *pin, HANDLE *pout, HANDLE *perr) {
bool inherit_stdout = inherit & SC_INHERIT_STDOUT; bool inherit_stdout = inherit & SC_STDOUT;
bool inherit_stderr = inherit & SC_INHERIT_STDERR; bool inherit_stderr = inherit & SC_STDERR;
// If pout is defined, then inherit MUST NOT contain SC_INHERIT_STDOUT. // If pout is defined, then inherit MUST NOT contain SC_STDOUT.
assert(!pout || !inherit_stdout); assert(!pout || !inherit_stdout);
// If perr is defined, then inherit MUST NOT contain SC_INHERIT_STDERR. // If perr is defined, then inherit MUST NOT contain SC_STDERR.
assert(!perr || !inherit_stderr); assert(!perr || !inherit_stderr);
// Add 1 per non-NULL pointer
unsigned handle_count = !!pin
+ (pout || inherit_stdout)
+ (perr || inherit_stderr);
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC; enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
@@ -85,52 +90,57 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit,
HANDLE handles[3]; HANDLE handles[3];
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL; 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; si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
unsigned handle_count = 0; if (handle_count) {
if (pin) { unsigned i = 0;
si.StartupInfo.hStdInput = stdin_read_handle; if (pin) {
handles[handle_count++] = si.StartupInfo.hStdInput; si.StartupInfo.hStdInput = stdin_read_handle;
} handles[i++] = si.StartupInfo.hStdInput;
if (pout || inherit_stdout) { }
si.StartupInfo.hStdOutput = pout ? stdout_write_handle if (pout || inherit_stdout) {
: GetStdHandle(STD_OUTPUT_HANDLE); si.StartupInfo.hStdOutput = pout ? stdout_write_handle
handles[handle_count++] = si.StartupInfo.hStdOutput; : GetStdHandle(STD_OUTPUT_HANDLE);
} handles[i++] = si.StartupInfo.hStdOutput;
if (perr || inherit_stderr) { }
si.StartupInfo.hStdError = perr ? stderr_write_handle if (perr || inherit_stderr) {
: GetStdHandle(STD_ERROR_HANDLE); si.StartupInfo.hStdError = perr ? stderr_write_handle
handles[handle_count++] = si.StartupInfo.hStdError; : GetStdHandle(STD_ERROR_HANDLE);
} handles[i++] = si.StartupInfo.hStdError;
}
SIZE_T size; SIZE_T size;
// Call it once to know the required buffer size // Call it once to know the required buffer size
BOOL ok = BOOL ok =
InitializeProcThreadAttributeList(NULL, 1, 0, &size) InitializeProcThreadAttributeList(NULL, 1, 0, &size)
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER; || GetLastError() == ERROR_INSUFFICIENT_BUFFER;
if (!ok) { if (!ok) {
goto error_close_stderr; goto error_close_stderr;
} }
lpAttributeList = malloc(size); lpAttributeList = malloc(size);
if (!lpAttributeList) { if (!lpAttributeList) {
goto error_close_stderr; goto error_close_stderr;
} }
ok = InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &size); ok = InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &size);
if (!ok) { if (!ok) {
free(lpAttributeList); free(lpAttributeList);
goto error_close_stderr; goto error_close_stderr;
} }
ok = UpdateProcThreadAttribute(lpAttributeList, 0, ok = UpdateProcThreadAttribute(lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
handle_count * sizeof(HANDLE), NULL, NULL); handles, handle_count * sizeof(HANDLE),
if (!ok) { NULL, NULL);
goto error_free_attribute_list; if (!ok) {
} goto error_free_attribute_list;
}
si.lpAttributeList = lpAttributeList; si.lpAttributeList = lpAttributeList;
}
char *cmd = malloc(CMD_MAX_LEN); char *cmd = malloc(CMD_MAX_LEN);
if (!cmd || !build_cmd(cmd, CMD_MAX_LEN, argv)) { if (!cmd || !build_cmd(cmd, CMD_MAX_LEN, argv)) {
@@ -144,9 +154,10 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit,
goto error_free_attribute_list; goto error_free_attribute_list;
} }
ok = CreateProcessW(NULL, wide, NULL, NULL, TRUE, BOOL bInheritHandles = handle_count > 0;
EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, DWORD dwCreationFlags = handle_count > 0 ? EXTENDED_STARTUPINFO_PRESENT : 0;
&si.StartupInfo, &pi); BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles,
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
free(wide); free(wide);
if (!ok) { if (!ok) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) { if (GetLastError() == ERROR_FILE_NOT_FOUND) {

View File

@@ -67,16 +67,15 @@ enum sc_process_result {
SC_PROCESS_ERROR_MISSING_BINARY, SC_PROCESS_ERROR_MISSING_BINARY,
}; };
#define SC_INHERIT_NONE 0 #define SC_STDOUT (1 << 0)
#define SC_INHERIT_STDOUT (1 << 0) #define SC_STDERR (1 << 1)
#define SC_INHERIT_STDERR (1 << 1)
/** /**
* Execute the command and write the process id to `pid` * Execute the command and write the process id to `pid`
* *
* The parameter `inherit` is a ORed value of SC_INHERIT_* flags. It indicates * The parameter `inherit` is a OR of any of SC_STDOUT and SC_STDERR. It
* if stdout and stderr must be inherited from the scrcpy process (in other * indicates if stdout and stderr must be inherited from the scrcpy process (in
* words, if the process must output to the scrcpy console). * other words, if the process must output to the scrcpy console).
*/ */
enum sc_process_result enum sc_process_result
sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit); sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit);
@@ -88,8 +87,8 @@ sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit);
* (`perr`). * (`perr`).
* *
* The parameter `inherit` has the same semantics as in `sc_process_execute()`. * The parameter `inherit` has the same semantics as in `sc_process_execute()`.
* If `pout` is not NULL, then `inherit` MUST NOT contain SC_INHERIT_STDOUT. * If `pout` is not NULL, then `inherit` MUST NOT contain SC_STDOUT.
* If `perr` is not NULL, then `inherit` MUST NOT contain SC_INHERIT_STDERR. * If `perr` is not NULL, then `inherit` MUST NOT contain SC_STDERR.
*/ */
enum sc_process_result enum sc_process_result
sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit, sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit,