From 84f5c503df1bd1b6ec034a9800b36b85f6798ea0 Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 9 Sep 2025 00:41:59 -0500 Subject: [PATCH] ensure createprocess children don't share pipes --- src/base/base.h | 2 +- src/base/base_math.c | 22 +- src/base/base_uni.c | 2 +- src/base/base_win32/base_win32_job.c | 34 ++- src/base/base_win32/base_win32_job.h | 3 + src/draw/draw.c | 2 +- src/font/font.c | 2 +- src/gpu/gpu_dx12/gpu_dx12.c | 9 +- src/gpu/gpu_dx12/gpu_dx12.h | 3 +- src/meta/meta.c | 52 ++-- src/meta/meta_os/meta_os.h | 1 + .../meta_os/meta_os_win32/meta_os_win32.c | 236 ++++++++++++------ .../meta_os/meta_os_win32/meta_os_win32.h | 5 + src/pp/pp.c | 14 +- 14 files changed, 250 insertions(+), 137 deletions(-) diff --git a/src/base/base.h b/src/base/base.h index df7626bc..ed638a52 100644 --- a/src/base/base.h +++ b/src/base/base.h @@ -207,7 +207,7 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t); #endif //- Static -#define LocalPersist static +#define PERSIST static #define Global static /* TODO: Remove this */ #define internal static diff --git a/src/base/base_math.c b/src/base/base_math.c index 9aea475a..993c983d 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -164,7 +164,7 @@ i64 SignF64(f64 f) /* Taken from https://gist.github.com/orlp/3551590 */ u64 PowU64(u64 base, u8 exp) { - LocalPersist const u8 highest_bit_set[] = { + PERSIST const u8 highest_bit_set[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, @@ -281,8 +281,8 @@ u64 AlignU64Pow2(u64 x) * https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_logf.c */ f32 LnF32(f32 x) { - LocalPersist const f32 ln2_hi = 6.9313812256e-01f; - LocalPersist const f32 ln2_lo = 9.0580006145e-06f; + PERSIST const f32 ln2_hi = 6.9313812256e-01f; + PERSIST const f32 ln2_lo = 9.0580006145e-06f; i32 x_int = *(i32 *)&x; @@ -376,14 +376,14 @@ f32 LnF32(f32 x) * https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_expf.c */ f32 ExpF32(f32 x) { - LocalPersist const f32 half[2] = { 0.5, -0.5 }; - LocalPersist const f32 o_threshold = 8.8721679688e+01f; - LocalPersist const f32 u_threshold = -1.0397208405e+02f; - LocalPersist const f32 ln2_hi[2] = { 6.9314575195e-01f, -6.9314575195e-01f }; - LocalPersist const f32 ln2_lo[2] = { 1.4286067653e-06f, -1.4286067653e-06f }; - LocalPersist const f32 inv_ln2 = 1.4426950216e+00f; - LocalPersist const f32 huge = 1.0e+30f; - LocalPersist const f32 two_m100 = 7.8886090522e-31f; + PERSIST const f32 half[2] = { 0.5, -0.5 }; + PERSIST const f32 o_threshold = 8.8721679688e+01f; + PERSIST const f32 u_threshold = -1.0397208405e+02f; + PERSIST const f32 ln2_hi[2] = { 6.9314575195e-01f, -6.9314575195e-01f }; + PERSIST const f32 ln2_lo[2] = { 1.4286067653e-06f, -1.4286067653e-06f }; + PERSIST const f32 inv_ln2 = 1.4426950216e+00f; + PERSIST const f32 huge = 1.0e+30f; + PERSIST const f32 two_m100 = 7.8886090522e-31f; u32 x_uint = *(u32 *)&x; i32 x_sign_bit = (i32)((x_uint >> 31) & 1); diff --git a/src/base/base_uni.c b/src/base/base_uni.c index 685fe2b0..7fe84a9f 100644 --- a/src/base/base_uni.c +++ b/src/base/base_uni.c @@ -5,7 +5,7 @@ Utf8DecodeResult DecodeUtf8(String str) { - LocalPersist const u8 lengths[32] = { + const u8 lengths[32] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5 }; diff --git a/src/base/base_win32/base_win32_job.c b/src/base/base_win32/base_win32_job.c index 8ac7e52b..9addd36f 100644 --- a/src/base/base_win32/base_win32_job.c +++ b/src/base/base_win32/base_win32_job.c @@ -358,6 +358,20 @@ void W32_WaitReleaseThread(W32_Thread *thread) //////////////////////////////// //~ Win32 wait list +W32_WaitBin *W32_WaitBinFromAddr(u64 addr) +{ + W32_SharedJobCtx *g = &W32_shared_job_ctx; + u64 mixed = RandU64FromSeed(addr); + return &g->wait_addr_bins[mixed % W32_NumWaitAddrBins]; +} + +W32_WaitBin *W32_WaitBinFromTime(u64 time) +{ + W32_SharedJobCtx *g = &W32_shared_job_ctx; + u64 mixed = RandU64FromSeed(time); + return &g->wait_addr_bins[mixed % W32_NumWaitTimeBins]; +} + /* REQUIRED: Caller must have acquired `wake_lock` for each fiber in array */ void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers) { @@ -378,7 +392,7 @@ void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers) W32_WaitList *wait_time_list = 0; if (wait_addr != 0) { - wait_addr_bin = &g->wait_addr_bins[wait_addr % W32_NumWaitAddrBins]; + wait_addr_bin = W32_WaitBinFromAddr(wait_addr); LockTicketMutex(&wait_addr_bin->lock); for (W32_WaitList *tmp = wait_addr_bin->first_wait_list; tmp && !wait_addr_list; tmp = tmp->next_in_bin) { @@ -390,7 +404,7 @@ void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers) } if (wait_time != 0) { - wait_time_bin = &g->wait_time_bins[wait_time % W32_NumWaitTimeBins]; + wait_time_bin = W32_WaitBinFromTime(wait_time); LockTicketMutex(&wait_time_bin->lock); for (W32_WaitList *tmp = wait_time_bin->first_wait_list; tmp && !wait_time_list; tmp = tmp->next_in_bin) { @@ -586,10 +600,8 @@ void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers) void W32_WakeByAddress(void *addr, i32 count) { TempArena scratch = BeginScratchNoConflict(); - W32_SharedJobCtx *g = &W32_shared_job_ctx; - u64 wait_addr_bin_index = (u64)addr % W32_NumWaitAddrBins; - W32_WaitBin *wait_addr_bin = &g->wait_addr_bins[wait_addr_bin_index]; + W32_WaitBin *wait_addr_bin = W32_WaitBinFromAddr((u64)addr); W32_WaitList *wait_addr_list = 0; /* Get list of waiting fibers */ @@ -648,10 +660,8 @@ void W32_WakeByAddress(void *addr, i32 count) void W32_WakeByTime(u64 time) { TempArena scratch = BeginScratchNoConflict(); - W32_SharedJobCtx *g = &W32_shared_job_ctx; - u64 wait_time_bin_index = (u64)time % W32_NumWaitTimeBins; - W32_WaitBin *wait_time_bin = &g->wait_time_bins[wait_time_bin_index]; + W32_WaitBin *wait_time_bin = W32_WaitBinFromTime(time); W32_WaitList *wait_time_list = 0; /* Build list of waiters to resume */ @@ -914,7 +924,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg) /* TODO: Pin non-worker threads to other cores */ HANDLE thread_handle = GetCurrentThread(); - if (pool->thread_priority) + if (pool->thread_priority != 0) { __profn("Set priority"); b32 success = SetThreadPriority(thread_handle, pool->thread_priority) != 0; @@ -1083,10 +1093,8 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg) wait_time = current_scheduler_cycle + MaxI64((i64)((f64)wait_timeout_ns / (f64)current_scheduler_cycle_period_ns), 1); } - u64 wait_addr_bin_index = (u64)wait_addr % W32_NumWaitAddrBins; - u64 wait_time_bin_index = (u64)wait_time % W32_NumWaitTimeBins; - W32_WaitBin *wait_addr_bin = &g->wait_addr_bins[wait_addr_bin_index]; - W32_WaitBin *wait_time_bin = &g->wait_time_bins[wait_time_bin_index]; + W32_WaitBin *wait_addr_bin = W32_WaitBinFromAddr((u64)wait_addr); + W32_WaitBin *wait_time_bin = W32_WaitBinFromTime((u64)wait_time); if (wait_addr != 0) LockTicketMutex(&wait_addr_bin->lock); { diff --git a/src/base/base_win32/base_win32_job.h b/src/base/base_win32/base_win32_job.h index 8d3990df..076aaf62 100644 --- a/src/base/base_win32/base_win32_job.h +++ b/src/base/base_win32/base_win32_job.h @@ -275,6 +275,9 @@ void W32_WaitReleaseThread(W32_Thread *thread); //////////////////////////////// //~ Wait list operations +W32_WaitBin *W32_WaitBinFromAddr(u64 addr); +W32_WaitBin *W32_WaitBinFromTime(u64 time); + void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers); void W32_WakeByAddress(void *addr, i32 count); void W32_WakeByTime(u64 time); diff --git a/src/draw/draw.c b/src/draw/draw.c index 30d5936a..3a4c704e 100644 --- a/src/draw/draw.c +++ b/src/draw/draw.c @@ -94,7 +94,7 @@ void D_DrawCircle(GPU_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detai void D_DrawQuad(GPU_RenderSig *sig, Quad quad, u32 color) { - LocalPersist u32 indices_array[6] = { + PERSIST const u32 indices_array[6] = { 0, 1, 2, 0, 2, 3 }; diff --git a/src/font/font.c b/src/font/font.c index 860adbee..c2e88277 100644 --- a/src/font/font.c +++ b/src/font/font.c @@ -6,7 +6,7 @@ JobDef(F_LoadJob, sig, _) __prof; TempArena scratch = BeginScratchNoConflict(); - Readonly LocalPersist u32 font_codes[] = { + PERSIST Readonly u32 font_codes[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, 0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, diff --git a/src/gpu/gpu_dx12/gpu_dx12.c b/src/gpu/gpu_dx12/gpu_dx12.c index 8d4065cc..db12e920 100644 --- a/src/gpu/gpu_dx12/gpu_dx12.c +++ b/src/gpu/gpu_dx12/gpu_dx12.c @@ -5,7 +5,7 @@ GPU_D12_SharedState GPU_D12_shared_state = ZI; GPU_D12_FiberState *GPU_D12_FiberStateFromId(i16 fiber_id) { - LocalPersist GPU_D12_FiberState *fiber_states[MaxFibers] = ZI; + PERSIST GPU_D12_FiberState *fiber_states[MaxFibers] = ZI; GPU_D12_FiberState *result = fiber_states[fiber_id]; if (!result) { @@ -16,6 +16,12 @@ GPU_D12_FiberState *GPU_D12_FiberStateFromId(i16 fiber_id) return result; } +GPU_D12_SharedState *GPU_D12_GetSharedState(void) +{ + PERSIST GPU_D12_SharedState g = ZI; + return &g; +} + //////////////////////////////// //~ Helpers @@ -69,6 +75,7 @@ void GPU_D12_EndRawCommandList(GPU_D12_RawCommandList *cl) void GPU_Startup(void) { + GPU_D12_SharedState *g = GPU_D12_GetSharedState(); } //////////////////////////////// diff --git a/src/gpu/gpu_dx12/gpu_dx12.h b/src/gpu/gpu_dx12/gpu_dx12.h index f16a457b..d12f4ff7 100644 --- a/src/gpu/gpu_dx12/gpu_dx12.h +++ b/src/gpu/gpu_dx12/gpu_dx12.h @@ -158,12 +158,11 @@ Struct(GPU_D12_SharedState) i32 _; }; -extern GPU_D12_SharedState GPU_D12_shared_state; - //////////////////////////////// //~ State operations GPU_D12_FiberState *GPU_D12_FiberStateFromId(i16 fiber_id); +GPU_D12_SharedState *GPU_D12_GetSharedState(void); //////////////////////////////// //~ Helpers diff --git a/src/meta/meta.c b/src/meta/meta.c index fb75cea5..84f2c9e7 100644 --- a/src/meta/meta.c +++ b/src/meta/meta.c @@ -65,21 +65,13 @@ /* TODO: Move this to OS layer */ void Echo(String msg) { - HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (console_handle != INVALID_HANDLE_VALUE) - { - WriteFile(console_handle, msg.text, msg.len, 0, 0); - } + OS_Echo(msg); } void EchoLine(String msg) { - HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (console_handle != INVALID_HANDLE_VALUE) - { - WriteFile(console_handle, msg.text, msg.len, 0, 0); - WriteFile(console_handle, "\n", 1, 0, 0); - } + OS_Echo(msg); + OS_Echo(Lit("\n")); } Struct(LineCol) @@ -113,13 +105,21 @@ LineCol LineColFromPos(String data, i64 pos) //////////////////////////////// //~ OS command job -JobDecl(RunCommandJob, { String *cmds; OS_CommandResult *results; }); +Struct(RunCommandResult) +{ + OS_CommandResult cmd_result; + i64 elapsed_ns; +}; + +JobDecl(RunCommandJob, { String *cmds; RunCommandResult *results; }); JobDef(RunCommandJob, sig, id) { + i64 start_ns = TimeNs(); Arena *arena = PermArena(); String cmd = sig->cmds[id]; - OS_CommandResult *result = &sig->results[id]; - *result = OS_RunCommand(arena, cmd); + RunCommandResult *result = &sig->results[id]; + result->cmd_result = OS_RunCommand(arena, cmd); + result->elapsed_ns = TimeNs() - start_ns; } //////////////////////////////// @@ -514,7 +514,7 @@ JobDef(StepJob, sig, id) //- Compile shaders String *compile_cmds = PushStructs(arena, String, shader_entries_count); - OS_CommandResult *compile_results = PushStructs(arena, OS_CommandResult, shader_entries_count); + RunCommandResult *compile_results = PushStructs(arena, RunCommandResult, shader_entries_count); { i32 i = 0; for (ShaderEntry *e = first_shader_entry; e; e = e->next) @@ -525,7 +525,7 @@ JobDef(StepJob, sig, id) : Lit("vs_6_6"); String *compile_cmd = &compile_cmds[i]; *compile_cmd = StringF(arena, - "dxc.exe -T %F -E %F -Fo %F/%F %F %F", + "cmd /c dxc.exe -T %F -E %F -Fo %F/%F %F %F", FmtString(target), FmtString(e->name), FmtString(shaders_out_dir), @@ -544,15 +544,16 @@ JobDef(StepJob, sig, id) i32 i = 0; for (ShaderEntry *e = first_shader_entry; e; e = e->next) { - OS_CommandResult compile_result = compile_results[i]; + RunCommandResult compile_result = compile_results[i]; + OS_CommandResult cmd_result = compile_result.cmd_result; if (result->return_code == 0) { - PushStringToList(arena, output, StringF(arena, "%F:%F", FmtString(F_GetFileName(gpu_out_file)), FmtString(e->name))); - if (compile_result.output.len > 0) + PushStringToList(arena, output, StringF(arena, "%F:%F %Fs", FmtString(F_GetFileName(gpu_out_file)), FmtString(e->name), FmtFloat(SecondsFromNs(compile_result.elapsed_ns)))); + if (cmd_result.output.len > 0) { - PushStringToList(arena, output, compile_result.output); + PushStringToList(arena, output, cmd_result.output); } - result->return_code = compile_result.code; + result->return_code = cmd_result.code; } ++i; } @@ -989,8 +990,6 @@ void StartupMeta(void) Counter step_counter = ZI; RunJob(countof(params_array), StepJob, JobPool_Hyper, JobPriority_Normal, &step_counter, .params = params_array, .results = results_array); - - EchoLine(Lit("[Compiling]")); YieldOnCounter(&step_counter); //////////////////////////////// @@ -1011,13 +1010,13 @@ void StartupMeta(void) String shader_output = StringFromList(arena, shader_result->output_lines, Lit("\n")); String resource_output = StringFromList(arena, resource_result->output_lines, Lit("\n")); - EchoLine(StringF(arena, "----- Built C in %Fs", FmtFloat(SecondsFromNs(program_result->elapsed_ns)))); + EchoLine(StringF(arena, ">>>>> Built C in %Fs", FmtFloat(SecondsFromNs(program_result->elapsed_ns)))); if (program_output.len > 0) EchoLine(program_output); - EchoLine(StringF(arena, "----- Built shaders in %Fs", FmtFloat(SecondsFromNs(shader_result->elapsed_ns)))); + EchoLine(StringF(arena, ">>>>> Built shaders in %Fs", FmtFloat(SecondsFromNs(shader_result->elapsed_ns)))); if (shader_output.len > 0) EchoLine(shader_output); - EchoLine(StringF(arena, "----- Built resources in %Fs", FmtFloat(SecondsFromNs(resource_result->elapsed_ns)))); + EchoLine(StringF(arena, ">>>>> Built resources in %Fs", FmtFloat(SecondsFromNs(resource_result->elapsed_ns)))); if (resource_output.len > 0) EchoLine(resource_output); } @@ -1033,7 +1032,6 @@ void StartupMeta(void) String shader_obj_files_str = StringFromList(arena, shader_result->obj_files, Lit(" ")); String resource_obj_files_str = StringFromList(arena, resource_result->obj_files, Lit(" ")); - EchoLine(Lit("[Linking]")); String cmd = StringF(arena, "cmd /c link.exe %F %F %F /OUT:%F %F %F", FmtString(program_obj_files_str), diff --git a/src/meta/meta_os/meta_os.h b/src/meta/meta_os/meta_os.h index 0f83c332..a9a17a46 100644 --- a/src/meta/meta_os/meta_os.h +++ b/src/meta/meta_os/meta_os.h @@ -53,4 +53,5 @@ void OS_Rm(String path); //////////////////////////////// //~ @hookdecl Shell operations +void OS_Echo(String msg); OS_CommandResult OS_RunCommand(Arena *arena, String cmd); diff --git a/src/meta/meta_os/meta_os_win32/meta_os_win32.c b/src/meta/meta_os/meta_os_win32/meta_os_win32.c index 53882b9c..987d8f9f 100644 --- a/src/meta/meta_os/meta_os_win32/meta_os_win32.c +++ b/src/meta/meta_os/meta_os_win32/meta_os_win32.c @@ -1,3 +1,30 @@ +//////////////////////////////// +//~ Win32 helpers + +String W32_StringFromError(Arena *arena, DWORD err) +{ + String result = ZI; + char *msg_cstr = 0; + i64 len = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&msg_cstr, + 0, + 0); + if (len > 0) + { + result = PushString(arena, TrimWhitespace(StringFromCstr(msg_cstr, len))); + LocalFree(msg_cstr); + } + else + { + result = StringF(arena, "Unknown win32 error - %F", FmtHex(err)); + } + return result; +} + //////////////////////////////// //~ @hookdef Startup hook @@ -181,93 +208,158 @@ void OS_Rm(String path) //////////////////////////////// //~ @hookdef Shell hooks +void OS_Echo(String msg) +{ + HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (console_handle != INVALID_HANDLE_VALUE) + { + WriteFile(console_handle, msg.text, msg.len, 0, 0); + } +} + OS_CommandResult OS_RunCommand(Arena *arena, String cmd) { TempArena scratch = BeginScratch(arena); OS_CommandResult result = ZI; + b32 ok = 1; wchar_t *cmd_wstr = WstrFromString(scratch.arena, cmd); SECURITY_ATTRIBUTES sa = ZI; sa.nLength = sizeof(sa); - sa.bInheritHandle = 1; + sa.bInheritHandle = 0; - HANDLE pipe_read, pipe_write; - if (CreatePipe(&pipe_read, &pipe_write, &sa, 0)) + /* Create pipe */ + HANDLE pipe_read = 0; + HANDLE pipe_write = 0; + if (ok) { - SetHandleInformation(pipe_read, HANDLE_FLAG_INHERIT, 0); - - STARTUPINFO si = ZI; - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = pipe_write; - si.hStdError = pipe_write; - - PROCESS_INFORMATION pi = ZI; - - result.output.text = PushDry(arena, u8); - if (!CreateProcessW(0, cmd_wstr, 0, 0, 1, 0, 0, 0, &si, &pi)) + ok = CreatePipe(&pipe_read, &pipe_write, &sa, 0) != 0; + if (!ok) { - DWORD err = GetLastError(); - char *msg_cstr = 0; - i64 len = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - 0, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&msg_cstr, - 0, - 0); - if (len > 0) - { - result.output = PushString(arena, StringFromCstr(msg_cstr, len)); - LocalFree(msg_cstr); - } - else - { - result.output = Lit("Failed to create process"); - } - result.code = -1; - } else { - CloseHandle(pipe_write); - b32 exit_code_valid = 0; - i32 exit_code = 0; - b32 stdout_finished = 0; - while (!stdout_finished) - { - u8 buff[4096] = ZI; - DWORD bytes_read = 0; - if (!ReadFile(pipe_read, buff, countof(buff), &bytes_read, 0)) - { - if (GetLastError() == ERROR_BROKEN_PIPE) - { - GetExitCodeProcess(pi.hProcess, &exit_code); - exit_code_valid = 1; - } - stdout_finished = 1; - } - PushStructsNoZero(arena, u8, bytes_read); - CopyBytes(result.output.text + result.output.len, buff, bytes_read); - result.output.len += bytes_read; - } - - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - - if (exit_code_valid) - { - result.code = exit_code; - } else { - result.code = -1; - } + result.output = Lit("Failed to create pipe"); + pipe_read = 0; + pipe_write = 0; } - - CloseHandle(pipe_read); } - else + + /* Duplicate pipe for child process */ + HANDLE child_pipe_write = 0; + if (ok) + { + ok = DuplicateHandle(GetCurrentProcess(), pipe_write, GetCurrentProcess(), &child_pipe_write, 0, 1, DUPLICATE_SAME_ACCESS) != 0; + if (!ok) + { + result.output = Lit("Failed to create child pipe"); + child_pipe_write = 0; + } + } + + /* Initialize attrs list */ + LPPROC_THREAD_ATTRIBUTE_LIST attrs = ZI; + if (ok) + { + u64 attrs_size = 0; + InitializeProcThreadAttributeList(0, 1, 0, &attrs_size); + ok = attrs_size > 0; + if (ok) + { + attrs = PushBytes(scratch.arena, attrs_size, 64); + ok = InitializeProcThreadAttributeList(attrs, 1, 0, &attrs_size) != 0; + } + if (!ok) + { + result.output = Lit("Failed to initialize attrs list"); + } + } + + /* Build the handle inheritance whitelist */ + if (ok) { + HANDLE inherit_list[] = { child_pipe_write }; + ok = UpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherit_list, sizeof(inherit_list), 0, 0) != 0; + if (!ok) + { + result.output = Lit("Failed to update attributes"); + } + } + + /* Create process */ + /* TODO: Allow caller to set child process's thread affinity by job pool */ + HANDLE process = 0; + HANDLE process_thread = 0; + if (ok) + { + PROCESS_INFORMATION pi = ZI; + STARTUPINFOEXW si = ZI; + si.StartupInfo.cb = sizeof(si); + si.StartupInfo.dwFlags = STARTF_USESTDHANDLES; + si.StartupInfo.hStdOutput = child_pipe_write; + si.StartupInfo.hStdError = child_pipe_write; + si.lpAttributeList = attrs; + ok = CreateProcessW(0, cmd_wstr, 0, 0, 1, EXTENDED_STARTUPINFO_PRESENT, 0, 0, &si.StartupInfo, &pi) != 0; + if (ok) + { + process = pi.hProcess; + process_thread = pi.hThread; + } + else + { + result.output = W32_StringFromError(arena, GetLastError()); + } + /* Close write pipe handles */ + { + CloseHandle(child_pipe_write); + CloseHandle(pipe_write); + child_pipe_write = 0; + pipe_write = 0; + } + } + + /* Read process output */ + if (ok) + { + result.output.text = PushDry(arena, u8); + b32 exit_code_valid = 0; + i32 exit_code = 0; + b32 stdout_finished = 0; + while (!stdout_finished) + { + u8 buff[4096] = ZI; + DWORD bytes_read = 0; + if (!ReadFile(pipe_read, buff, countof(buff), &bytes_read, 0)) + { + DWORD err = GetLastError(); + if (err == ERROR_BROKEN_PIPE) + { + GetExitCodeProcess(process, &exit_code); + exit_code_valid = 1; + } + else + { + result.output.len += W32_StringFromError(arena, err).len; + } + stdout_finished = 1; + } + PushStructsNoZero(arena, u8, bytes_read); + CopyBytes(result.output.text + result.output.len, buff, bytes_read); + result.output.len += bytes_read; + } + if (exit_code_valid) + { + result.code = exit_code; + } + } + + /* Close handles */ + if (attrs) DeleteProcThreadAttributeList(attrs); + if (process_thread) CloseHandle(process_thread); + if (process) CloseHandle(process); + if (child_pipe_write) CloseHandle(child_pipe_write); + if (pipe_read) CloseHandle(pipe_read); + if (pipe_write) CloseHandle(pipe_write); + + if (!ok && result.code == 0) { - result.output = Lit("Failed to create pipe"); result.code = -1; } diff --git a/src/meta/meta_os/meta_os_win32/meta_os_win32.h b/src/meta/meta_os/meta_os_win32/meta_os_win32.h index 97a6bdf4..b66fd51f 100644 --- a/src/meta/meta_os/meta_os_win32/meta_os_win32.h +++ b/src/meta/meta_os/meta_os_win32/meta_os_win32.h @@ -3,3 +3,8 @@ #pragma comment(lib, "kernel32") #pragma comment(lib, "user32") + +//////////////////////////////// +//~ Win32 helpers + +String W32_StringFromError(Arena *arena, DWORD err); diff --git a/src/pp/pp.c b/src/pp/pp.c index e9d4bd4f..b282b157 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -288,7 +288,7 @@ void DrawDebugConsole(i32 level, b32 minimized) f32 spacing = 0; f32 bg_margin = 5; - LocalPersist u32 colors[P_LogLevel_Count][2] = ZI; + u32 colors[P_LogLevel_Count][2] = ZI; SetBytes(colors, 0xFF, sizeof(colors)); #if 1 colors[P_LogLevel_Debug][0] = Rgb32F(0.4, 0.1, 0.4); colors[P_LogLevel_Debug][1] = Rgb32F(0.5, 0.2, 0.5); @@ -2149,12 +2149,12 @@ void UpdateUser(P_Window *window) if (g->shade_target && !EqVec2I32(g->render_size, GPU_GetTextureSize(g->shade_target))) { __profn("Release render resources"); - GPU_ReleaseResource(g->albedo, g->render_fence, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->emittance, g->render_fence, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->emittance_flood_read, g->render_fence, GPU_ReleaseFlag_None); + GPU_ReleaseResource(g->albedo, g->render_fence, GPU_ReleaseFlag_None); + GPU_ReleaseResource(g->emittance, g->render_fence, GPU_ReleaseFlag_None); + GPU_ReleaseResource(g->emittance_flood_read, g->render_fence, GPU_ReleaseFlag_None); GPU_ReleaseResource(g->emittance_flood_target, g->render_fence, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->shade_read, g->render_fence, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->shade_target, g->render_fence, GPU_ReleaseFlag_None); + GPU_ReleaseResource(g->shade_read, g->render_fence, GPU_ReleaseFlag_None); + GPU_ReleaseResource(g->shade_target, g->render_fence, GPU_ReleaseFlag_None); g->shade_target = 0; } if (!g->shade_target) @@ -2181,7 +2181,7 @@ void UpdateUser(P_Window *window) /* Acquire transfer buffers */ /* TODO: Make these static */ - LocalPersist u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; + u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; GPU_Resource *quad_index_buffer = AcquireTransferBuffer(countof(quad_indices), sizeof(*quad_indices), quad_indices); GPU_Resource *material_instance_buffer = AcquireTransferBufferFromArena(g->material_instances_count, g->material_instances_arena); GPU_Resource *ui_rect_instance_buffer = AcquireTransferBufferFromArena(g->ui_rect_instances_count, g->ui_rect_instances_arena);