command outputs; ipc command output reception & writing to stdout

This commit is contained in:
Ryan Fleury
2025-06-05 16:08:53 -07:00
parent 3d7bfb41b8
commit c282e7d4be
7 changed files with 164 additions and 69 deletions
+1 -1
View File
@@ -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);
+2 -1
View File
@@ -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)},
+4 -1
View File
@@ -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];
+1
View File
@@ -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 }
+20 -2
View File
@@ -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
+2
View File
@@ -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;
+134 -64
View File
@@ -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;