Expose flags 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. PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
This commit is contained in:
parent
b9b8b6aab8
commit
f801d8b312
5 changed files with 48 additions and 14 deletions
|
@ -181,7 +181,7 @@ adb_execute_p(const char *serial, const char *const adb_cmd[], size_t len,
|
||||||
|
|
||||||
sc_pid pid;
|
sc_pid pid;
|
||||||
enum sc_process_result r =
|
enum sc_process_result r =
|
||||||
sc_process_execute_p(argv, &pid, NULL, pout, NULL);
|
sc_process_execute_p(argv, &pid, 0, NULL, pout, NULL);
|
||||||
if (r != SC_PROCESS_SUCCESS) {
|
if (r != SC_PROCESS_SUCCESS) {
|
||||||
show_adb_err_msg(r, argv);
|
show_adb_err_msg(r, argv);
|
||||||
pid = SC_PROCESS_NONE;
|
pid = SC_PROCESS_NONE;
|
||||||
|
|
|
@ -11,8 +11,11 @@
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
enum sc_process_result
|
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 flags,
|
||||||
int *pin, int *pout, int *perr) {
|
int *pin, int *pout, int *perr) {
|
||||||
|
bool inherit_stdout = !pout && !(flags & SC_PROCESS_NO_STDOUT);
|
||||||
|
bool inherit_stderr = !perr && !(flags & SC_PROCESS_NO_STDERR);
|
||||||
|
|
||||||
int in[2];
|
int in[2];
|
||||||
int out[2];
|
int out[2];
|
||||||
int err[2];
|
int err[2];
|
||||||
|
@ -90,20 +93,30 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid,
|
||||||
}
|
}
|
||||||
close(in[1]);
|
close(in[1]);
|
||||||
}
|
}
|
||||||
|
// Do not close stdin in the child process, this makes adb fail on Linux
|
||||||
|
|
||||||
if (pout) {
|
if (pout) {
|
||||||
if (out[1] != STDOUT_FILENO) {
|
if (out[1] != STDOUT_FILENO) {
|
||||||
dup2(out[1], STDOUT_FILENO);
|
dup2(out[1], STDOUT_FILENO);
|
||||||
close(out[1]);
|
close(out[1]);
|
||||||
}
|
}
|
||||||
close(out[0]);
|
close(out[0]);
|
||||||
|
} else if (!inherit_stdout) {
|
||||||
|
// Close stdout in the child process
|
||||||
|
close(STDOUT_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perr) {
|
if (perr) {
|
||||||
if (err[1] != STDERR_FILENO) {
|
if (err[1] != STDERR_FILENO) {
|
||||||
dup2(err[1], STDERR_FILENO);
|
dup2(err[1], STDERR_FILENO);
|
||||||
close(err[1]);
|
close(err[1]);
|
||||||
}
|
}
|
||||||
close(err[0]);
|
close(err[0]);
|
||||||
|
} else if (!inherit_stderr) {
|
||||||
|
// Close stderr in the child process
|
||||||
|
close(STDERR_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
enum sc_process_result err;
|
enum sc_process_result err;
|
||||||
if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) {
|
if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) {
|
||||||
|
|
|
@ -24,12 +24,17 @@ 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,
|
sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned flags,
|
||||||
HANDLE *pin, HANDLE *pout, HANDLE *perr) {
|
HANDLE *pin, HANDLE *pout, HANDLE *perr) {
|
||||||
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
|
bool inherit_stdout = !pout && !(flags & SC_PROCESS_NO_STDOUT);
|
||||||
|
bool inherit_stderr = !perr && !(flags & SC_PROCESS_NO_STDERR);
|
||||||
|
|
||||||
// Add 1 per non-NULL pointer
|
// 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;
|
SECURITY_ATTRIBUTES sa;
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
@ -85,12 +90,14 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
||||||
si.StartupInfo.hStdInput = stdin_read_handle;
|
si.StartupInfo.hStdInput = stdin_read_handle;
|
||||||
handles[i++] = si.StartupInfo.hStdInput;
|
handles[i++] = si.StartupInfo.hStdInput;
|
||||||
}
|
}
|
||||||
if (pout) {
|
if (pout || inherit_stdout) {
|
||||||
si.StartupInfo.hStdOutput = stdout_write_handle;
|
si.StartupInfo.hStdOutput = pout ? stdout_write_handle
|
||||||
|
: GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
handles[i++] = si.StartupInfo.hStdOutput;
|
handles[i++] = si.StartupInfo.hStdOutput;
|
||||||
}
|
}
|
||||||
if (perr) {
|
if (perr || inherit_stderr) {
|
||||||
si.StartupInfo.hStdError = stderr_write_handle;
|
si.StartupInfo.hStdError = perr ? stderr_write_handle
|
||||||
|
: GetStdHandle(STD_ERROR_HANDLE);
|
||||||
handles[i++] = si.StartupInfo.hStdError;
|
handles[i++] = si.StartupInfo.hStdError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +147,9 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL bInheritHandles = handle_count > 0;
|
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 ? EXTENDED_STARTUPINFO_PRESENT
|
||||||
|
: DETACHED_PROCESS;
|
||||||
BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles,
|
BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles,
|
||||||
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
|
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
|
||||||
free(wide);
|
free(wide);
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
enum sc_process_result
|
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 flags) {
|
||||||
return sc_process_execute_p(argv, pid, NULL, NULL, NULL);
|
return sc_process_execute_p(argv, pid, flags, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
|
|
|
@ -67,20 +67,32 @@ enum sc_process_result {
|
||||||
SC_PROCESS_ERROR_MISSING_BINARY,
|
SC_PROCESS_ERROR_MISSING_BINARY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SC_PROCESS_NO_STDOUT (1 << 0)
|
||||||
|
#define SC_PROCESS_NO_STDERR (1 << 1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the command and write the process id to `pid`
|
* Execute the command and write the process id to `pid`
|
||||||
|
*
|
||||||
|
* The `flags` argument is a bitwise OR of the following values:
|
||||||
|
* - SC_PROCESS_NO_STDOUT
|
||||||
|
* - SC_PROCESS_NO_STDERR
|
||||||
|
*
|
||||||
|
* It indicates if stdout and stderr must be inherited from the scrcpy process
|
||||||
|
* (i.e. 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);
|
sc_process_execute(const char *const argv[], sc_pid *pid, unsigned flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the command and write the process id to `pid`
|
* Execute the command and write the process id to `pid`
|
||||||
*
|
*
|
||||||
* If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr
|
* If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr
|
||||||
* (`perr`).
|
* (`perr`).
|
||||||
|
*
|
||||||
|
* The `flags` argument has the same semantics as in `sc_process_execute()`.
|
||||||
*/
|
*/
|
||||||
enum sc_process_result
|
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 flags,
|
||||||
sc_pipe *pin, sc_pipe *pout, sc_pipe *perr);
|
sc_pipe *pin, sc_pipe *pout, sc_pipe *perr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue