Re: BREAKing into Euphoria
- Posted by ghaberek (admin) Feb 26, 2022
- 1435 views
I plan to look more at the debugging features later
So much for that, I already figured it out. Turns out it was pretty easy, but I'm still not sure how safe this is. The SIGINT (Ctrl+C) signal interrupt handler is configured in InitExecute(). The first step was to borrow some code from trace_command() and plop that into INT_Handler().
// be_rterror.c:1668 void INT_Handler(int sig_no) /* control-c, control-break */ { UNUSED(sig_no); if (trace_enabled) { /* start tracing */ signal(SIGINT, INT_Handler); TraceOn = TRUE; color_trace = TRUE; #ifdef _WIN32 show_console(); #endif return; } ...
This worked great... when with trace was enabled. Turns out trace_enabled is always set to TRUE and the backend relies on the frontend to emit the necessary tracing ops. So my trick would act like allow_break(FALSE) without trace enabled. My solution was to grab trace_enabled from the parser section for with/without trace and pass that through to the backend.
-- global.e:617 export integer trace_enabled = FALSE
Edit: I made a small change here. Originally, trace_enabled would turn on-and-off depending on the last with/without trace statement. That's not going to work since tracing would be ignored if the last check was without trace, and any omitted tracing ops would be ignored. This makes trace_enabled "sticky" in that it will only ever turn on and won't ever turn off.
-- parser.e:4529 ... elsif equal(option, "trace") then if not BIND then OpTrace = on_off -- trace_enabled = on_off if on_off then trace_enabled = TRUE end if end if ...
-- backend.e:285 machine_proc(65, { ... trace_lines, trace_enabled, $ })
// be_machine.c:2842 object start_backend(object x) /* called by Euphoria-written front-end to run the back-end * * x is {symtab, topcode, subcode, names, line_table, miscellaneous } */ { ... trace_lines = get_pos_int(w, *(x_ptr->base+16)); trace_enabled = get_pos_int(w, *(x_ptr->base+17)); ...
That seems to do the trick. I made a simple little program that goes into a loop for 60 seconds and when I press Ctrl+C it jumps into the trace screen. Pressing q resumes execution until I press Ctrl+C again to jump back to trace, and pressing Q resumes execution and disables trace. Pressing Ctrl+C again from there stops the program normally.
include std/os.e with trace atom t0 = 0 atom t1 = time() atom t2 = t1 + 60 while t1 < t2 do if t1 > t0 then t0 = t1 ? t0 end if sleep(rand(10)/100) t1 = time() end while
This is a pretty neat feature to have, but I'll say it again loudly: I don't know enough about the interpreter yet to say how safe this is. Your app might crash. Weird things might happen.
-Greg