From c282e7d4be8e9104bdf1ec6bf824cffe5f82c960 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 5 Jun 2025 16:08:53 -0700 Subject: [PATCH] command outputs; ipc command output reception & writing to stdout --- src/dbg_engine/dbg_engine_core.c | 2 +- src/raddbg/generated/raddbg.meta.c | 3 +- src/raddbg/generated/raddbg.meta.h | 5 +- src/raddbg/raddbg.mdesk | 1 + src/raddbg/raddbg_core.c | 22 +++- src/raddbg/raddbg_core.h | 2 + src/raddbg/raddbg_main.c | 198 +++++++++++++++++++---------- 7 files changed, 164 insertions(+), 69 deletions(-) diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index befefe05..5339b8dd 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -840,7 +840,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, override_n = override_n->next) { String8 file_path = override_n->string; - String8 file_path_normalized = lower_from_str8(scratch.arena, file_path); + String8 file_path_normalized = lower_from_str8(scratch.arena, path_normalized_from_string(scratch.arena, file_path)); // rjf: binary -> rdi RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 3d70d781..3c41da85 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -437,7 +437,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[24] = {str8_lit_comp("thread"), str8_lit_comp("x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'call_stack':query}")}, }; -Rng1U64 rd_reg_slot_range_table[45] = +Rng1U64 rd_reg_slot_range_table[46] = { {0}, {OffsetOf(RD_Regs, machine), OffsetOf(RD_Regs, machine) + sizeof(CTRL_Handle)}, @@ -479,6 +479,7 @@ Rng1U64 rd_reg_slot_range_table[45] = {OffsetOf(RD_Regs, do_lister), OffsetOf(RD_Regs, do_lister) + sizeof(B32)}, {OffsetOf(RD_Regs, do_big_rows), OffsetOf(RD_Regs, do_big_rows) + sizeof(B32)}, {OffsetOf(RD_Regs, all_windows), OffsetOf(RD_Regs, all_windows) + sizeof(B32)}, +{OffsetOf(RD_Regs, non_graphical), OffsetOf(RD_Regs, non_graphical) + sizeof(B32)}, {OffsetOf(RD_Regs, dir2), OffsetOf(RD_Regs, dir2) + sizeof(Dir2)}, {OffsetOf(RD_Regs, string), OffsetOf(RD_Regs, string) + sizeof(String8)}, {OffsetOf(RD_Regs, cmd_name), OffsetOf(RD_Regs, cmd_name) + sizeof(String8)}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 7ef94f5d..42ef1b3a 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -48,6 +48,7 @@ RD_RegSlot_DoImplicitRoot, RD_RegSlot_DoLister, RD_RegSlot_DoBigRows, RD_RegSlot_AllWindows, +RD_RegSlot_NonGraphical, RD_RegSlot_Dir2, RD_RegSlot_String, RD_RegSlot_CmdName, @@ -474,6 +475,7 @@ B32 do_implicit_root; B32 do_lister; B32 do_big_rows; B32 all_windows; +B32 non_graphical; Dir2 dir2; String8 string; String8 cmd_name; @@ -569,6 +571,7 @@ Z(getting_started)\ .do_lister = rd_regs()->do_lister,\ .do_big_rows = rd_regs()->do_big_rows,\ .all_windows = rd_regs()->all_windows,\ +.non_graphical = rd_regs()->non_graphical,\ .dir2 = rd_regs()->dir2,\ .string = rd_regs()->string,\ .cmd_name = rd_regs()->cmd_name,\ @@ -580,7 +583,7 @@ extern String8 rd_tab_fast_path_view_name_table[24]; extern String8 rd_tab_fast_path_query_name_table[24]; extern RD_VocabInfo rd_vocab_info_table[345]; extern RD_NameSchemaInfo rd_name_schema_info_table[24]; -extern Rng1U64 rd_reg_slot_range_table[45]; +extern Rng1U64 rd_reg_slot_range_table[46]; extern String8 rd_binding_version_remap_old_name_table[8]; extern String8 rd_binding_version_remap_new_name_table[8]; extern String8 rd_icon_kind_text_table[75]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index bfa0b791..bc1f7a80 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -743,6 +743,7 @@ RD_RegTable: {B32 do_lister DoLister } {B32 do_big_rows DoBigRows } {B32 all_windows AllWindows } + {B32 non_graphical NonGraphical } {Dir2 dir2 Dir2 } {String8 string String } {String8 cmd_name CmdName } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 54473a22..92d84794 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -10588,6 +10588,13 @@ rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 string) rd_regs()->cursor = pair.pt; } }break; + case RD_RegSlot_Cfg: + if(str8_match(str8_prefix(string, 1), str8_lit("$"), 0)) + { + String8 numeric_part = str8_skip(string, 1); + RD_CfgID id = u64_from_str8(numeric_part, 16); + rd_regs()->cfg = id; + }break; case RD_RegSlot_Expr: { rd_regs()->expr = push_str8_copy(rd_frame_arena(), string); @@ -10782,6 +10789,7 @@ rd_init(CmdLine *cmdln) { rd_state->cmds_arenas[idx] = arena_alloc(); } + rd_state->cmd_output_arena = arena_alloc(); rd_state->popup_arena = arena_alloc(); rd_state->ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("top_level_ctx_menu")); rd_state->drop_completion_key = ui_key_from_string(ui_key_zero(), str8_lit("drop_completion_ctx_menu")); @@ -11086,6 +11094,11 @@ rd_frame(void) } B32 allow_text_hotkeys = !rd_state->text_edit_mode; rd_state->text_edit_mode = 0; + if(rd_state->frame_depth == 1) + { + arena_clear(rd_state->cmd_output_arena); + MemoryZeroStruct(&rd_state->cmd_outputs); + } ////////////////////////////// //- rjf: iterate all tabs, touch their view-states @@ -15493,10 +15506,11 @@ rd_frame(void) RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); RD_Cfg *bp = rd_cfg_new(project, str8_lit("breakpoint")); rd_cmd(RD_CmdKind_RelocateCfg, .cfg = bp->id); - if(rd_regs()->do_lister) + if(rd_regs()->do_lister && !rd_regs()->non_graphical) { rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", bp->id), .do_lister = 0); } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", bp->id); } } }break; @@ -15798,7 +15812,11 @@ rd_frame(void) rd_cfg_newf(wdir, "%S/", working_directory); } rd_cmd(RD_CmdKind_SelectTarget, .cfg = target->id); - rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", target->id)); + if(!rd_regs()->non_graphical) + { + rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", target->id)); + } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", target->id); }break; //- rjf: jit-debugger registration diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 523160a7..f202ca7f 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -634,6 +634,8 @@ struct RD_State Arena *cmds_arenas[2]; RD_CmdList cmds[2]; U64 cmds_gen; + Arena *cmd_output_arena; + String8List cmd_outputs; // rjf: popup state UI_Key popup_key; diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 78356848..f4012c2b 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -295,9 +295,12 @@ struct IPCInfo //- rjf: IPC resources #define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4) StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement); -global OS_Handle ipc_signal_semaphore = {0}; -global OS_Handle ipc_lock_semaphore = {0}; -global U8 *ipc_shared_memory_base = 0; +global OS_Handle ipc_sender2main_signal_semaphore = {0}; +global OS_Handle ipc_sender2main_lock_semaphore = {0}; +global U8 *ipc_sender2main_shared_memory_base = 0; +global OS_Handle ipc_main2sender_signal_semaphore = {0}; +global OS_Handle ipc_main2sender_lock_semaphore = {0}; +global U8 *ipc_main2sender_shared_memory_base = 0; global U8 ipc_s2m_ring_buffer[MB(4)] = {0}; global U64 ipc_s2m_ring_write_pos = 0; global U64 ipc_s2m_ring_read_pos = 0; @@ -313,11 +316,11 @@ ipc_signaler_thread__entry_point(void *p) ThreadNameF("[rd] ipc signaler thread"); for(;;) { - if(os_semaphore_take(ipc_signal_semaphore, max_U64)) + if(os_semaphore_take(ipc_sender2main_signal_semaphore, max_U64)) { - if(os_semaphore_take(ipc_lock_semaphore, max_U64)) + if(os_semaphore_take(ipc_sender2main_lock_semaphore, max_U64)) { - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); OS_MutexScope(ipc_s2m_ring_mutex) for(;;) @@ -335,7 +338,7 @@ ipc_signaler_thread__entry_point(void *p) os_condition_variable_broadcast(ipc_s2m_ring_cv); os_send_wakeup_event(); ipc_info->msg_size = 0; - os_semaphore_drop(ipc_lock_semaphore); + os_semaphore_drop(ipc_sender2main_lock_semaphore); } } } @@ -367,42 +370,6 @@ entry_point(CmdLine *cmd_line) { Temp scratch = scratch_begin(0, 0); - //- rjf: windows -> turn off output handles, as we need to control those for target processes -#if OS_WINDOWS - HANDLE output_handles[3] = - { - GetStdHandle(STD_INPUT_HANDLE), - GetStdHandle(STD_OUTPUT_HANDLE), - GetStdHandle(STD_ERROR_HANDLE), - }; - for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) - { - B32 duplicate = 0; - for(U64 idx2 = 0; idx2 < idx; idx2 += 1) - { - if(output_handles[idx2] == output_handles[idx]) - { - duplicate = 1; - break; - } - } - if(duplicate) - { - output_handles[idx] = 0; - } - } - for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) - { - if(output_handles[idx] != 0) - { - CloseHandle(output_handles[idx]); - } - } - SetStdHandle(STD_INPUT_HANDLE, 0); - SetStdHandle(STD_OUTPUT_HANDLE, 0); - SetStdHandle(STD_ERROR_HANDLE, 0); -#endif - //- rjf: unpack command line arguments ExecMode exec_mode = ExecMode_Normal; B32 auto_run = 0; @@ -446,6 +413,42 @@ entry_point(CmdLine *cmd_line) default: case ExecMode_Normal: { + //- rjf: windows -> turn off output handles, as we need to control those for target processes +#if OS_WINDOWS + HANDLE output_handles[3] = + { + GetStdHandle(STD_INPUT_HANDLE), + GetStdHandle(STD_OUTPUT_HANDLE), + GetStdHandle(STD_ERROR_HANDLE), + }; + for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) + { + B32 duplicate = 0; + for(U64 idx2 = 0; idx2 < idx; idx2 += 1) + { + if(output_handles[idx2] == output_handles[idx]) + { + duplicate = 1; + break; + } + } + if(duplicate) + { + output_handles[idx] = 0; + } + } + for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) + { + if(output_handles[idx] != 0) + { + CloseHandle(output_handles[idx]); + } + } + SetStdHandle(STD_INPUT_HANDLE, 0); + SetStdHandle(STD_OUTPUT_HANDLE, 0); + SetStdHandle(STD_ERROR_HANDLE, 0); +#endif + //- rjf: manual layer initialization { r_init(cmd_line); @@ -521,21 +524,35 @@ entry_point(CmdLine *cmd_line) { Temp scratch = scratch_begin(0, 0); U32 instance_pid = os_get_process_info()->pid; - String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", instance_pid); - String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", instance_pid); - String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", instance_pid); - OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); - ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); - ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name); - ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name); + + // rjf: set up cross-process sender -> main ring buffer + String8 ipc_sender2main_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_shared_memory_%i_", instance_pid); + String8 ipc_sender2main_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_signal_semaphore_%i_", instance_pid); + String8 ipc_sender2main_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_lock_semaphore_%i_", instance_pid); + OS_Handle ipc_sender2main_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_sender2main_shared_memory_name); + ipc_sender2main_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_sender2main_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_sender2main_signal_semaphore = os_semaphore_alloc(0, 1, ipc_sender2main_signal_semaphore_name); + ipc_sender2main_lock_semaphore = os_semaphore_alloc(1, 1, ipc_sender2main_lock_semaphore_name); + + // rjf: set up cross-process main -> sender ring buffer + String8 ipc_main2sender_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_shared_memory_%i_", instance_pid); + String8 ipc_main2sender_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_signal_semaphore_%i_", instance_pid); + String8 ipc_main2sender_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_lock_semaphore_%i_", instance_pid); + OS_Handle ipc_main2sender_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_main2sender_shared_memory_name); + ipc_main2sender_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_main2sender_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_main2sender_signal_semaphore = os_semaphore_alloc(0, 1, ipc_main2sender_signal_semaphore_name); + ipc_main2sender_lock_semaphore = os_semaphore_alloc(1, 1, ipc_main2sender_lock_semaphore_name); + + // rjf: set up ipc-receiver -> main thread ring buffer; launch signaler thread ipc_s2m_ring_mutex = os_mutex_alloc(); ipc_s2m_ring_cv = os_condition_variable_alloc(); - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; - if(ipc_shared_memory_base != 0) + IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; + if(ipc_sender2main_shared_memory_base != 0) { MemoryZeroStruct(ipc_info); os_thread_launch(ipc_signaler_thread__entry_point, 0, 0); } + scratch_end(scratch); } @@ -544,6 +561,7 @@ entry_point(CmdLine *cmd_line) for(B32 quit = 0; !quit;) { //- rjf: consume IPC messages, dispatch UI commands + B32 ipc_command_frame = 0; { Temp scratch = scratch_begin(0, 0); B32 consumed = 0; @@ -554,6 +572,7 @@ entry_point(CmdLine *cmd_line) if(unconsumed_size >= sizeof(U64)) { consumed = 1; + ipc_command_frame = 1; ipc_s2m_ring_read_pos += ring_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size); msg.size = Min(msg.size, unconsumed_size); msg.str = push_array(scratch.arena, U8, msg.size); @@ -632,6 +651,24 @@ entry_point(CmdLine *cmd_line) jit_attach = 0; rd_cmd(RD_CmdKind_Attach, .pid = jit_pid); } + + //- rjf: gather command outputs & write them + if(ipc_command_frame) + { + if(ipc_main2sender_shared_memory_base != 0 && + os_semaphore_take(ipc_main2sender_lock_semaphore, os_now_microseconds()+5000000)) + { + IPCInfo *ipc_info = (IPCInfo *)ipc_main2sender_shared_memory_base; + U8 *buffer = (U8 *)(ipc_info+1); + U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); + StringJoin join = {str8_lit(""), str8_lit("\0"), str8_lit("")}; + String8 msg = str8_list_join(scratch.arena, &rd_state->cmd_outputs, &join); + ipc_info->msg_size = Min(buffer_max, msg.size); + MemoryCopy(buffer, msg.str, ipc_info->msg_size); + os_semaphore_drop(ipc_main2sender_signal_semaphore); + os_semaphore_drop(ipc_main2sender_lock_semaphore); + } + } } } @@ -674,29 +711,62 @@ entry_point(CmdLine *cmd_line) } //- rjf: grab destination instance's shared memory resources - String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", dst_pid); - String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", dst_pid); - String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", dst_pid); - OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); - ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); - ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name); - ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name); + String8 ipc_sender2main_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_shared_memory_%i_", dst_pid); + String8 ipc_sender2main_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_signal_semaphore_%i_", dst_pid); + String8 ipc_sender2main_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_lock_semaphore_%i_", dst_pid); + OS_Handle ipc_sender2main_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_sender2main_shared_memory_name); + ipc_sender2main_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_sender2main_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_sender2main_signal_semaphore = os_semaphore_alloc(0, 1, ipc_sender2main_signal_semaphore_name); + ipc_sender2main_lock_semaphore = os_semaphore_alloc(1, 1, ipc_sender2main_lock_semaphore_name); + String8 ipc_main2sender_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_shared_memory_%i_", dst_pid); + String8 ipc_main2sender_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_signal_semaphore_%i_", dst_pid); + String8 ipc_main2sender_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_lock_semaphore_%i_", dst_pid); + OS_Handle ipc_main2sender_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_main2sender_shared_memory_name); + ipc_main2sender_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_main2sender_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_main2sender_signal_semaphore = os_semaphore_alloc(0, 1, ipc_main2sender_signal_semaphore_name); + ipc_main2sender_lock_semaphore = os_semaphore_alloc(1, 1, ipc_main2sender_lock_semaphore_name); //- rjf: got resources -> write message - if(ipc_shared_memory_base != 0 && - os_semaphore_take(ipc_lock_semaphore, max_U64)) + B32 wrote_message = 0; + if(ipc_sender2main_shared_memory_base != 0 && + os_semaphore_take(ipc_sender2main_lock_semaphore, max_U64)) { - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + wrote_message = 1; + IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; U8 *buffer = (U8 *)(ipc_info+1); U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; String8 msg = str8_list_join(scratch.arena, &cmd_line->inputs, &join); ipc_info->msg_size = Min(buffer_max, msg.size); MemoryCopy(buffer, msg.str, ipc_info->msg_size); - os_semaphore_drop(ipc_signal_semaphore); - os_semaphore_drop(ipc_lock_semaphore); + os_semaphore_drop(ipc_sender2main_signal_semaphore); + os_semaphore_drop(ipc_sender2main_lock_semaphore); } + //- rjf: wrote message -> wait for outputs, read outputs + String8List outputs = {0}; + if(wrote_message && + ipc_main2sender_shared_memory_base != 0 && + os_semaphore_take(ipc_main2sender_signal_semaphore, os_now_microseconds()+10000000)) + { + if(os_semaphore_take(ipc_main2sender_lock_semaphore, max_U64)) + { + IPCInfo *ipc_info = (IPCInfo *)ipc_main2sender_shared_memory_base; + String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); + msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); + U8 split_char = 0; + outputs = str8_split(scratch.arena, msg, &split_char, 1, 0); + os_semaphore_drop(ipc_main2sender_lock_semaphore); + } + } + + //- rjf: write outputs to stdout + for(String8Node *n = outputs.first; n != 0; n = n->next) + { + fwrite(n->string.str, 1, n->string.size, stdout); + } + fflush(stdout); + scratch_end(scratch); }break;