Skip to content

Commit

Permalink
Expose inherit flag for process execution
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rom1v committed Nov 24, 2021
1 parent 10c613d commit 922733c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 15 deletions.
6 changes: 5 additions & 1 deletion app/src/adb.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,12 @@ adb_execute_p(const char *serial, const char *const adb_cmd[],

memcpy(&argv[i], adb_cmd, len * sizeof(const char *));
argv[len + i] = NULL;
unsigned inherit = SC_STDERR;
if (!pout) {
inherit |= SC_STDOUT;
}
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;
Expand Down
21 changes: 20 additions & 1 deletion app/src/sys/unix/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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) {
Expand Down
31 changes: 22 additions & 9 deletions app/src/sys/win/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,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);
Expand Down Expand Up @@ -79,18 +89,19 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
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;
}

Expand Down Expand Up @@ -140,7 +151,9 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
}

BOOL bInheritHandles = handle_count > 0;
DWORD dwCreationFlags = handle_count > 0 ? EXTENDED_STARTUPINFO_PRESENT : 0;
// DETACHED_PROCESS to disable stdin, stdout and stderr
DWORD dwCreationFlags = handle_count == 0 ? DETACHED_PROCESS
: EXTENDED_STARTUPINFO_PRESENT;
BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles,
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
free(wide);
Expand Down
4 changes: 2 additions & 2 deletions app/src/util/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions app/src/util/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/**
Expand Down

0 comments on commit 922733c

Please sign in to comment.