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)
static RzThreadLock *subproc_mutex = NULL;
static long refcount = 0;
static bool has_procthreadattr = false;
static volatile long pipe_id = 0;
static DWORD mode_stdin;
static DWORD mode_stdout;
static DWORD mode_stderr;
typedef struct subprocess_windows_t {
RzThreadLock *subproc_mutex;
long refcount;
bool has_procthreadattr;
volatile long pipe_id;
DWORD mode_stdin;
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) {
// see https://stackoverflow.com/a/419736
@ -61,7 +65,7 @@ static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURIT
sz = 4096;
}
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);
if (!*pipe_read) {
return FALSE;
@ -79,29 +83,29 @@ static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURIT
static RzThreadLock *get_subprocess_lock(void) {
RzThreadLock *lock;
do {
lock = InterlockedCompareExchangePointer(&subproc_mutex, INVALID_POINTER_VALUE, INVALID_POINTER_VALUE);
lock = InterlockedCompareExchangePointer(&subwin.subproc_mutex, INVALID_POINTER_VALUE, INVALID_POINTER_VALUE);
} while (!lock);
return lock;
}
RZ_API bool rz_subprocess_init(void) {
long ref = InterlockedIncrement(&refcount);
long ref = InterlockedIncrement(&subwin.refcount);
RzThreadLock *lock = NULL;
if (ref == 1) {
lock = rz_th_lock_new(false);
if (!lock) {
InterlockedExchangePointer(&subproc_mutex, INVALID_POINTER_VALUE);
InterlockedDecrement(&refcount);
InterlockedExchangePointer(&subwin.subproc_mutex, INVALID_POINTER_VALUE);
InterlockedDecrement(&subwin.refcount);
return false;
}
// Enter lock before making it available, so we are the first to run
rz_th_lock_enter(lock);
InterlockedExchangePointer(&subproc_mutex, lock);
InterlockedExchangePointer(&subwin.subproc_mutex, lock);
} else {
// Spin until theres a lock available or lock initialization failed
lock = get_subprocess_lock();
if (lock == INVALID_POINTER_VALUE) {
InterlockedDecrement(&refcount);
InterlockedDecrement(&subwin.refcount);
return false;
}
rz_th_lock_enter(lock);
@ -113,12 +117,12 @@ RZ_API bool rz_subprocess_init(void) {
}
// Save current console mode
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode_stdin);
GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &mode_stdout);
GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &mode_stderr);
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &subwin.mode_stdin);
GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &subwin.mode_stdout);
GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &subwin.mode_stderr);
#if NTDDI_VERSION >= NTDDI_VISTA
if (!has_procthreadattr && IsWindowsVistaOrGreater()) {
if (!subwin.has_procthreadattr && IsWindowsVistaOrGreater()) {
HMODULE kernel32 = LoadLibraryW(L"kernel32");
if (!kernel32) {
rz_sys_perror("LoadLibraryW(L\"kernel32\")");
@ -128,7 +132,7 @@ RZ_API bool rz_subprocess_init(void) {
lpUpdateProcThreadAttribute = (UpdateProcThreadAttribute_t)GetProcAddress(kernel32, "UpdateProcThreadAttribute");
lpDeleteProcThreadAttributeList = (DeleteProcThreadAttributeList_t)GetProcAddress(kernel32, "DeleteProcThreadAttributeList");
if (lpInitializeProcThreadAttributeList && lpUpdateProcThreadAttribute && lpDeleteProcThreadAttributeList) {
has_procthreadattr = true;
subwin.has_procthreadattr = true;
}
FreeLibrary(kernel32);
}
@ -140,22 +144,22 @@ leave:
RZ_API void rz_subprocess_fini(void) {
RzThreadLock *lock = NULL;
do {
if (InterlockedCompareExchange(&refcount, -1, -1) == 0) {
if (InterlockedCompareExchange(&subwin.refcount, -1, -1) == 0) {
// Shouldn't happen, someone called this function excessively
rz_warn_if_reached();
return;
}
lock = InterlockedExchangePointer(&subproc_mutex, NULL);
lock = InterlockedExchangePointer(&subwin.subproc_mutex, NULL);
} while (!lock);
if (InterlockedDecrement(&refcount) > 0) {
InterlockedExchangePointer(&subproc_mutex, lock);
if (InterlockedDecrement(&subwin.refcount) > 0) {
InterlockedExchangePointer(&subwin.subproc_mutex, lock);
return;
}
SetEnvironmentVariableW(L"RZ_PIPE_PATH", NULL);
// Restore console mode
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode_stdin);
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), mode_stdout);
SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), mode_stderr);
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), subwin.mode_stdin);
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), subwin.mode_stdout);
SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), subwin.mode_stderr);
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;
#if NTDDI_VERSION >= NTDDI_VISTA
STARTUPINFOEXW start_infoex = { .StartupInfo.cb = sizeof(STARTUPINFOEXW) };
if (has_procthreadattr) {
if (subwin.has_procthreadattr) {
SIZE_T attr_list_size = 0;
if (!lpInitializeProcThreadAttributeList(NULL, 1, 0, &attr_list_size) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {