Moved windows static vars into struct.
This commit is contained in:
parent
84e63af3d2
commit
28c691651f
1 changed files with 31 additions and 27 deletions
|
|
@ -47,13 +47,17 @@ struct rz_subprocess_t {
|
||||||
|
|
||||||
#define INVALID_POINTER_VALUE ((void *)PTRDIFF_MAX)
|
#define INVALID_POINTER_VALUE ((void *)PTRDIFF_MAX)
|
||||||
|
|
||||||
static RzThreadLock *subproc_mutex = NULL;
|
typedef struct subprocess_windows_t {
|
||||||
static long refcount = 0;
|
RzThreadLock *subproc_mutex;
|
||||||
static bool has_procthreadattr = false;
|
long refcount;
|
||||||
static volatile long pipe_id = 0;
|
bool has_procthreadattr;
|
||||||
static DWORD mode_stdin;
|
volatile long pipe_id;
|
||||||
static DWORD mode_stdout;
|
DWORD mode_stdin;
|
||||||
static DWORD mode_stderr;
|
DWORD mode_stdout;
|
||||||
|
DWORD mode_stderr;
|
||||||
|
} SubprocessWindows;
|
||||||
|
|
||||||
|
static SubprocessWindows subwin = { 0 };
|
||||||
|
|
||||||
static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURITY_ATTRIBUTES attrs, DWORD sz, DWORD read_mode, DWORD write_mode) {
|
static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURITY_ATTRIBUTES attrs, DWORD sz, DWORD read_mode, DWORD write_mode) {
|
||||||
// see https://stackoverflow.com/a/419736
|
// see https://stackoverflow.com/a/419736
|
||||||
|
|
@ -61,7 +65,7 @@ static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURIT
|
||||||
sz = 4096;
|
sz = 4096;
|
||||||
}
|
}
|
||||||
WCHAR name[MAX_PATH];
|
WCHAR name[MAX_PATH];
|
||||||
_snwprintf_s(name, _countof(name), sizeof(name), L"\\\\.\\pipe\\rz-pipe-subproc.%d.%ld", (int)GetCurrentProcessId(), (long)InterlockedIncrement(&pipe_id));
|
_snwprintf_s(name, _countof(name), sizeof(name), L"\\\\.\\pipe\\rz-pipe-subproc.%d.%ld", (int)GetCurrentProcessId(), (long)InterlockedIncrement(&subwin.pipe_id));
|
||||||
*pipe_read = CreateNamedPipeW(name, PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, sz, sz, 120 * 1000, attrs);
|
*pipe_read = CreateNamedPipeW(name, PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, sz, sz, 120 * 1000, attrs);
|
||||||
if (!*pipe_read) {
|
if (!*pipe_read) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
@ -79,29 +83,29 @@ static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURIT
|
||||||
static RzThreadLock *get_subprocess_lock(void) {
|
static RzThreadLock *get_subprocess_lock(void) {
|
||||||
RzThreadLock *lock;
|
RzThreadLock *lock;
|
||||||
do {
|
do {
|
||||||
lock = InterlockedCompareExchangePointer(&subproc_mutex, INVALID_POINTER_VALUE, INVALID_POINTER_VALUE);
|
lock = InterlockedCompareExchangePointer(&subwin.subproc_mutex, INVALID_POINTER_VALUE, INVALID_POINTER_VALUE);
|
||||||
} while (!lock);
|
} while (!lock);
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZ_API bool rz_subprocess_init(void) {
|
RZ_API bool rz_subprocess_init(void) {
|
||||||
long ref = InterlockedIncrement(&refcount);
|
long ref = InterlockedIncrement(&subwin.refcount);
|
||||||
RzThreadLock *lock = NULL;
|
RzThreadLock *lock = NULL;
|
||||||
if (ref == 1) {
|
if (ref == 1) {
|
||||||
lock = rz_th_lock_new(false);
|
lock = rz_th_lock_new(false);
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
InterlockedExchangePointer(&subproc_mutex, INVALID_POINTER_VALUE);
|
InterlockedExchangePointer(&subwin.subproc_mutex, INVALID_POINTER_VALUE);
|
||||||
InterlockedDecrement(&refcount);
|
InterlockedDecrement(&subwin.refcount);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Enter lock before making it available, so we are the first to run
|
// Enter lock before making it available, so we are the first to run
|
||||||
rz_th_lock_enter(lock);
|
rz_th_lock_enter(lock);
|
||||||
InterlockedExchangePointer(&subproc_mutex, lock);
|
InterlockedExchangePointer(&subwin.subproc_mutex, lock);
|
||||||
} else {
|
} else {
|
||||||
// Spin until theres a lock available or lock initialization failed
|
// Spin until theres a lock available or lock initialization failed
|
||||||
lock = get_subprocess_lock();
|
lock = get_subprocess_lock();
|
||||||
if (lock == INVALID_POINTER_VALUE) {
|
if (lock == INVALID_POINTER_VALUE) {
|
||||||
InterlockedDecrement(&refcount);
|
InterlockedDecrement(&subwin.refcount);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rz_th_lock_enter(lock);
|
rz_th_lock_enter(lock);
|
||||||
|
|
@ -113,12 +117,12 @@ RZ_API bool rz_subprocess_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save current console mode
|
// Save current console mode
|
||||||
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode_stdin);
|
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &subwin.mode_stdin);
|
||||||
GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &mode_stdout);
|
GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &subwin.mode_stdout);
|
||||||
GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &mode_stderr);
|
GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &subwin.mode_stderr);
|
||||||
|
|
||||||
#if NTDDI_VERSION >= NTDDI_VISTA
|
#if NTDDI_VERSION >= NTDDI_VISTA
|
||||||
if (!has_procthreadattr && IsWindowsVistaOrGreater()) {
|
if (!subwin.has_procthreadattr && IsWindowsVistaOrGreater()) {
|
||||||
HMODULE kernel32 = LoadLibraryW(L"kernel32");
|
HMODULE kernel32 = LoadLibraryW(L"kernel32");
|
||||||
if (!kernel32) {
|
if (!kernel32) {
|
||||||
rz_sys_perror("LoadLibraryW(L\"kernel32\")");
|
rz_sys_perror("LoadLibraryW(L\"kernel32\")");
|
||||||
|
|
@ -128,7 +132,7 @@ RZ_API bool rz_subprocess_init(void) {
|
||||||
lpUpdateProcThreadAttribute = (UpdateProcThreadAttribute_t)GetProcAddress(kernel32, "UpdateProcThreadAttribute");
|
lpUpdateProcThreadAttribute = (UpdateProcThreadAttribute_t)GetProcAddress(kernel32, "UpdateProcThreadAttribute");
|
||||||
lpDeleteProcThreadAttributeList = (DeleteProcThreadAttributeList_t)GetProcAddress(kernel32, "DeleteProcThreadAttributeList");
|
lpDeleteProcThreadAttributeList = (DeleteProcThreadAttributeList_t)GetProcAddress(kernel32, "DeleteProcThreadAttributeList");
|
||||||
if (lpInitializeProcThreadAttributeList && lpUpdateProcThreadAttribute && lpDeleteProcThreadAttributeList) {
|
if (lpInitializeProcThreadAttributeList && lpUpdateProcThreadAttribute && lpDeleteProcThreadAttributeList) {
|
||||||
has_procthreadattr = true;
|
subwin.has_procthreadattr = true;
|
||||||
}
|
}
|
||||||
FreeLibrary(kernel32);
|
FreeLibrary(kernel32);
|
||||||
}
|
}
|
||||||
|
|
@ -140,22 +144,22 @@ leave:
|
||||||
RZ_API void rz_subprocess_fini(void) {
|
RZ_API void rz_subprocess_fini(void) {
|
||||||
RzThreadLock *lock = NULL;
|
RzThreadLock *lock = NULL;
|
||||||
do {
|
do {
|
||||||
if (InterlockedCompareExchange(&refcount, -1, -1) == 0) {
|
if (InterlockedCompareExchange(&subwin.refcount, -1, -1) == 0) {
|
||||||
// Shouldn't happen, someone called this function excessively
|
// Shouldn't happen, someone called this function excessively
|
||||||
rz_warn_if_reached();
|
rz_warn_if_reached();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lock = InterlockedExchangePointer(&subproc_mutex, NULL);
|
lock = InterlockedExchangePointer(&subwin.subproc_mutex, NULL);
|
||||||
} while (!lock);
|
} while (!lock);
|
||||||
if (InterlockedDecrement(&refcount) > 0) {
|
if (InterlockedDecrement(&subwin.refcount) > 0) {
|
||||||
InterlockedExchangePointer(&subproc_mutex, lock);
|
InterlockedExchangePointer(&subwin.subproc_mutex, lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SetEnvironmentVariableW(L"RZ_PIPE_PATH", NULL);
|
SetEnvironmentVariableW(L"RZ_PIPE_PATH", NULL);
|
||||||
// Restore console mode
|
// Restore console mode
|
||||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode_stdin);
|
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), subwin.mode_stdin);
|
||||||
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), mode_stdout);
|
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), subwin.mode_stdout);
|
||||||
SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), mode_stderr);
|
SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), subwin.mode_stderr);
|
||||||
rz_th_lock_free(lock);
|
rz_th_lock_free(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,7 +377,7 @@ RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubproces
|
||||||
STARTUPINFOW *start_info = &start_info_short;
|
STARTUPINFOW *start_info = &start_info_short;
|
||||||
#if NTDDI_VERSION >= NTDDI_VISTA
|
#if NTDDI_VERSION >= NTDDI_VISTA
|
||||||
STARTUPINFOEXW start_infoex = { .StartupInfo.cb = sizeof(STARTUPINFOEXW) };
|
STARTUPINFOEXW start_infoex = { .StartupInfo.cb = sizeof(STARTUPINFOEXW) };
|
||||||
if (has_procthreadattr) {
|
if (subwin.has_procthreadattr) {
|
||||||
SIZE_T attr_list_size = 0;
|
SIZE_T attr_list_size = 0;
|
||||||
if (!lpInitializeProcThreadAttributeList(NULL, 1, 0, &attr_list_size) &&
|
if (!lpInitializeProcThreadAttributeList(NULL, 1, 0, &attr_list_size) &&
|
||||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue