mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-04-21 12:05:00 +00:00
process_inherit
This commit is contained in:
parent
c96dc6d2c4
commit
88e9c2b4af
5 changed files with 96 additions and 59 deletions
|
@ -132,8 +132,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_INHERIT_STDERR;
|
||||
if (!pout) {
|
||||
inherit |= SC_INHERIT_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;
|
||||
|
|
|
@ -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_INHERIT_STDOUT;
|
||||
bool inherit_stderr = inherit & SC_INHERIT_STDERR;
|
||||
|
||||
// If pout is defined, then inherit MUST NOT contain SC_INHERIT_STDOUT.
|
||||
assert(!pout || !inherit_stdout);
|
||||
// If perr is defined, then inherit MUST NOT contain SC_INHERIT_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) {
|
||||
|
|
|
@ -27,12 +27,17 @@ 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_INHERIT_STDOUT;
|
||||
bool inherit_stderr = inherit & SC_INHERIT_STDERR;
|
||||
|
||||
// Add 1 per non-NULL pointer
|
||||
unsigned handle_count = !!pin + !!pout + !!perr;
|
||||
// If pout is defined, then inherit MUST NOT contain SC_INHERIT_STDOUT.
|
||||
assert(!pout || !inherit_stdout);
|
||||
// If perr is defined, then inherit MUST NOT contain SC_INHERIT_STDERR.
|
||||
assert(!perr || !inherit_stderr);
|
||||
|
||||
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
|
||||
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
|
@ -80,53 +85,52 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
|||
HANDLE handles[3];
|
||||
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
|
||||
if (handle_count) {
|
||||
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||
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;
|
||||
handles[i++] = si.StartupInfo.hStdOutput;
|
||||
}
|
||||
if (perr) {
|
||||
si.StartupInfo.hStdError = stderr_write_handle;
|
||||
handles[i++] = si.StartupInfo.hStdError;
|
||||
}
|
||||
|
||||
SIZE_T size;
|
||||
// Call it once to know the required buffer size
|
||||
BOOL ok =
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &size)
|
||||
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER;
|
||||
if (!ok) {
|
||||
goto error_close_stderr;
|
||||
}
|
||||
|
||||
lpAttributeList = malloc(size);
|
||||
if (!lpAttributeList) {
|
||||
goto error_close_stderr;
|
||||
}
|
||||
|
||||
ok = InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &size);
|
||||
if (!ok) {
|
||||
free(lpAttributeList);
|
||||
goto error_close_stderr;
|
||||
}
|
||||
|
||||
ok = UpdateProcThreadAttribute(lpAttributeList, 0,
|
||||
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||
handles, handle_count * sizeof(HANDLE),
|
||||
NULL, NULL);
|
||||
if (!ok) {
|
||||
goto error_free_attribute_list;
|
||||
}
|
||||
|
||||
si.lpAttributeList = lpAttributeList;
|
||||
unsigned handle_count = 0;
|
||||
if (pin) {
|
||||
si.StartupInfo.hStdInput = stdin_read_handle;
|
||||
handles[handle_count++] = si.StartupInfo.hStdInput;
|
||||
}
|
||||
if (pout || inherit_stdout) {
|
||||
si.StartupInfo.hStdOutput = pout ? stdout_write_handle
|
||||
: GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
handles[handle_count++] = si.StartupInfo.hStdOutput;
|
||||
}
|
||||
if (perr || inherit_stderr) {
|
||||
si.StartupInfo.hStdError = perr ? stderr_write_handle
|
||||
: GetStdHandle(STD_ERROR_HANDLE);
|
||||
handles[handle_count++] = si.StartupInfo.hStdError;
|
||||
}
|
||||
|
||||
SIZE_T size;
|
||||
// Call it once to know the required buffer size
|
||||
BOOL ok =
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &size)
|
||||
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER;
|
||||
if (!ok) {
|
||||
goto error_close_stderr;
|
||||
}
|
||||
|
||||
lpAttributeList = malloc(size);
|
||||
if (!lpAttributeList) {
|
||||
goto error_close_stderr;
|
||||
}
|
||||
|
||||
ok = InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &size);
|
||||
if (!ok) {
|
||||
free(lpAttributeList);
|
||||
goto error_close_stderr;
|
||||
}
|
||||
|
||||
ok = UpdateProcThreadAttribute(lpAttributeList, 0,
|
||||
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles,
|
||||
handle_count * sizeof(HANDLE), NULL, NULL);
|
||||
if (!ok) {
|
||||
goto error_free_attribute_list;
|
||||
}
|
||||
|
||||
si.lpAttributeList = lpAttributeList;
|
||||
|
||||
char *cmd = malloc(CMD_MAX_LEN);
|
||||
if (!cmd || !build_cmd(cmd, CMD_MAX_LEN, argv)) {
|
||||
|
@ -140,10 +144,9 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
|||
goto error_free_attribute_list;
|
||||
}
|
||||
|
||||
BOOL bInheritHandles = handle_count > 0;
|
||||
DWORD dwCreationFlags = handle_count > 0 ? EXTENDED_STARTUPINFO_PRESENT : 0;
|
||||
BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles,
|
||||
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
|
||||
ok = CreateProcessW(NULL, wide, NULL, NULL, TRUE,
|
||||
EXTENDED_STARTUPINFO_PRESENT, NULL, NULL,
|
||||
&si.StartupInfo, &pi);
|
||||
free(wide);
|
||||
if (!ok) {
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -67,20 +67,31 @@ enum sc_process_result {
|
|||
SC_PROCESS_ERROR_MISSING_BINARY,
|
||||
};
|
||||
|
||||
#define SC_INHERIT_STDOUT (1 << 0)
|
||||
#define SC_INHERIT_STDERR (1 << 1)
|
||||
|
||||
/**
|
||||
* Execute the command and write the process id to `pid`
|
||||
*
|
||||
* The parameter `inherit` is a ORed value of SC_INHERIT_* flags. 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_INHERIT_STDOUT.
|
||||
* If `perr` is not NULL, then `inherit` MUST NOT contain SC_INHERIT_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);
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue