Moved windows static vars into struct.

This commit is contained in:
wargio 2024-05-22 14:38:59 +08:00 committed by Giovanni
parent 84e63af3d2
commit 28c691651f

View file

@ -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) {