Compare commits
2 Commits
windows_in
...
fix_inheri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
020b3510ae | ||
|
|
dcf9887f56 |
@@ -1,10 +1,5 @@
|
|||||||
// <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>
|
|
||||||
#define _WIN32_WINNT 0x0600 // For extended process API
|
|
||||||
|
|
||||||
#include "util/process.h"
|
#include "util/process.h"
|
||||||
|
|
||||||
#include <processthreadsapi.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
@@ -31,8 +26,7 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
|||||||
HANDLE *pin, HANDLE *pout, HANDLE *perr) {
|
HANDLE *pin, HANDLE *pout, HANDLE *perr) {
|
||||||
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
|
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
|
||||||
|
|
||||||
// Add 1 per non-NULL pointer
|
bool inherit_handles = pin || pout || perr;
|
||||||
unsigned handle_count = !!pin + !!pout + !!perr;
|
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
@@ -73,94 +67,45 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STARTUPINFOEXW si;
|
STARTUPINFOW si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
memset(&si, 0, sizeof(si));
|
memset(&si, 0, sizeof(si));
|
||||||
si.StartupInfo.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
HANDLE handles[3];
|
if (inherit_handles) {
|
||||||
|
si.dwFlags = STARTF_USESTDHANDLES;
|
||||||
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
|
|
||||||
if (handle_count) {
|
|
||||||
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
|
||||||
if (pin) {
|
if (pin) {
|
||||||
si.StartupInfo.hStdInput = stdin_read_handle;
|
si.hStdInput = stdin_read_handle;
|
||||||
}
|
}
|
||||||
if (pout) {
|
if (pout) {
|
||||||
si.StartupInfo.hStdOutput = stdout_write_handle;
|
si.hStdOutput = stdout_write_handle;
|
||||||
}
|
}
|
||||||
if (perr) {
|
if (perr) {
|
||||||
si.StartupInfo.hStdError = stderr_write_handle;
|
si.hStdError = stderr_write_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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),
|
|
||||||
NULL, NULL);
|
|
||||||
if (!ok) {
|
|
||||||
goto error_free_attribute_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
||||||
goto error_free_attribute_list;
|
*handle = NULL;
|
||||||
|
goto error_close_stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *wide = sc_str_to_wchars(cmd);
|
wchar_t *wide = sc_str_to_wchars(cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
if (!wide) {
|
if (!wide) {
|
||||||
LOGC("Could not allocate wide char string");
|
LOGC("Could not allocate wide char string");
|
||||||
goto error_free_attribute_list;
|
goto error_close_stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL bInheritHandles = handle_count > 0;
|
if (!CreateProcessW(NULL, wide, NULL, NULL, inherit_handles, 0, NULL, NULL,
|
||||||
DWORD dwCreationFlags = handle_count > 0 ? EXTENDED_STARTUPINFO_PRESENT : 0;
|
&si, &pi)) {
|
||||||
BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles,
|
free(wide);
|
||||||
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
|
*handle = NULL;
|
||||||
free(wide);
|
|
||||||
if (!ok) {
|
|
||||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||||
ret = SC_PROCESS_ERROR_MISSING_BINARY;
|
ret = SC_PROCESS_ERROR_MISSING_BINARY;
|
||||||
}
|
}
|
||||||
goto error_free_attribute_list;
|
goto error_close_stderr;
|
||||||
}
|
|
||||||
|
|
||||||
if (lpAttributeList) {
|
|
||||||
DeleteProcThreadAttributeList(lpAttributeList);
|
|
||||||
free(lpAttributeList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These handles are used by the child process, close them for this process
|
// These handles are used by the child process, close them for this process
|
||||||
@@ -174,15 +119,11 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
|||||||
CloseHandle(stderr_write_handle);
|
CloseHandle(stderr_write_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(wide);
|
||||||
*handle = pi.hProcess;
|
*handle = pi.hProcess;
|
||||||
|
|
||||||
return SC_PROCESS_SUCCESS;
|
return SC_PROCESS_SUCCESS;
|
||||||
|
|
||||||
error_free_attribute_list:
|
|
||||||
if (lpAttributeList) {
|
|
||||||
DeleteProcThreadAttributeList(lpAttributeList);
|
|
||||||
free(lpAttributeList);
|
|
||||||
}
|
|
||||||
error_close_stderr:
|
error_close_stderr:
|
||||||
if (perr) {
|
if (perr) {
|
||||||
CloseHandle(*perr);
|
CloseHandle(*perr);
|
||||||
@@ -229,7 +170,7 @@ sc_process_close(HANDLE handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
sc_pipe_read(HANDLE pipe, char *data, size_t len) {
|
sc_read_pipe(HANDLE pipe, char *data, size_t len) {
|
||||||
DWORD r;
|
DWORD r;
|
||||||
if (!ReadFile(pipe, data, len, &r, NULL)) {
|
if (!ReadFile(pipe, data, len, &r, NULL)) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -238,7 +179,7 @@ sc_pipe_read(HANDLE pipe, char *data, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sc_pipe_close(HANDLE pipe) {
|
sc_close_pipe(HANDLE pipe) {
|
||||||
if (!CloseHandle(pipe)) {
|
if (!CloseHandle(pipe)) {
|
||||||
LOGW("Cannot close pipe");
|
LOGW("Cannot close pipe");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,27 @@ net_perror(const char *s) {
|
|||||||
sc_socket
|
sc_socket
|
||||||
net_socket(void) {
|
net_socket(void) {
|
||||||
sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM, 0);
|
sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* To be able to communicate with a child process via stdin, stdout and
|
||||||
|
* stderr, the CreateProcess() parameter bInheritHandles must be set to
|
||||||
|
* TRUE. But this causes *all* handles to be inherited, including sockets.
|
||||||
|
*
|
||||||
|
* One possibility could be to use an extended API to set extra attributes
|
||||||
|
* on process creation:
|
||||||
|
* - <https://stackoverflow.com/a/28185363/1987178>
|
||||||
|
* - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>
|
||||||
|
* But it seems that this API is not available on MinGW (it does not
|
||||||
|
* compile).
|
||||||
|
*
|
||||||
|
* As an alternative, explicitly mark all sockets as non-inheritable.
|
||||||
|
*/
|
||||||
|
if (!SetHandleInformation((HANDLE) raw_sock, HANDLE_FLAG_INHERIT, 0)) {
|
||||||
|
closesocket(raw_sock);
|
||||||
|
return SC_SOCKET_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
sc_socket sock = wrap(raw_sock);
|
sc_socket sock = wrap(raw_sock);
|
||||||
if (sock == SC_SOCKET_NONE) {
|
if (sock == SC_SOCKET_NONE) {
|
||||||
net_perror("socket");
|
net_perror("socket");
|
||||||
|
|||||||
Reference in New Issue
Block a user