Re: BREAKing into Euphoria

new topic     » goto parent     » topic index » view thread      » older message » newer message
ghaberek said...

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

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu