From help-octave-request at bevo dot che dot wisc dot edu Fri Feb 20 14:58:41 2004 Subject: Ctrl-C and try-catch From: "John W. Eaton" To: Paul Kienzle Cc: help-octave at bevo dot che dot wisc dot edu Date: Fri, 20 Feb 2004 14:57:00 -0600 On 12-Dec-2003, Paul Kienzle wrote: | The following code prints 'no' if I hit control C or 'yes' if it | runs to completion: | | octave> try; for i=1:100000, x=i+1; end; 'yes', catch, 'no', end; | ans = no | | Is there any way to stop a try-catch from catching Ctrl-C? Or detect | if Ctrl-C is pressed so that I can throw it again in the interrupt? | Or tell Ctrl-C to return to the top level, skipping all try-catch | blocks? How about the following change? With it, I think the behavior for interrupts in things like unwind_protect "foo" for i = 1:100000 y = sin(i); endfor "bar" unwind_protect_cleanup try for j = 1:100000 z = cos(j); endfor catch "baz" end_try_catch end_unwind_protect is correct. Thanks, jwe libcruft/ChangeLog: 2004-02-20 John W. Eaton * misc/quit.h (OCTAVE_QUIT): Set octave_interrupt_state to -1 while we are handling interrupts. src/ChangeLog: 2004-02-20 John W. Eaton * sighandlers.cc (sigfpe_handler, sigpipe_handler): Don't increment octave_interrupt_state if it is less than 0. (sigint_handler): If octave_interrupt_state is less than zero, reset it. * pt-except.cc (do_catch_code): Call OCTAVE_QUIT here so the catch code won't run if an interrupt is pending. Don't run catch code if intterrupt_state is less than zero. Index: libcruft/misc/quit.h =================================================================== RCS file: /usr/local/cvsroot/octave/libcruft/misc/quit.h,v retrieving revision 1.12 diff -u -r1.12 quit.h --- libcruft/misc/quit.h 31 Oct 2003 03:07:05 -0000 1.12 +++ libcruft/misc/quit.h 20 Feb 2004 20:51:53 -0000 at @ -68,6 +68,10 @@ extern sig_atomic_t octave_interrupt_immediately; +// > 0: interrupt pending +// 0: no interrupt pending +// < 0: handling interrupt +// extern sig_atomic_t octave_interrupt_state; extern sig_atomic_t octave_allocation_error; at @ -79,9 +83,9 @@ #define OCTAVE_QUIT \ do \ { \ - if (octave_interrupt_state) \ + if (octave_interrupt_state > 0) \ { \ - octave_interrupt_state = 0; \ + octave_interrupt_state = -1; \ octave_throw_interrupt_exception (); \ } \ } \ Index: src/pt-except.cc =================================================================== RCS file: /usr/local/cvsroot/octave/src/pt-except.cc,v retrieving revision 1.18 diff -u -r1.18 pt-except.cc --- src/pt-except.cc 20 Jan 2004 23:04:46 -0000 1.18 +++ src/pt-except.cc 20 Feb 2004 20:52:03 -0000 at @ -57,7 +57,27 @@ static void do_catch_code (void *ptr) { - if (octave_interrupt_immediately) + // Is it safe to call OCTAVE_QUIT here? We are already running + // something on the unwind_protect stack, but the element for this + // action would have already been popped from the top of the stack, + // so we should not be attempting to run it again. + + OCTAVE_QUIT; + + // If we are interrupting immediately, or if an interrupt is in + // progress (octave_interrupt_state < 0), then we don't want to run + // the catch code (it should only run on errors, not interrupts). + + // If octave_interrupt_state is positive, an interrupt is pending. + // The only way that could happen would be for the interrupt to + // come in after the OCTAVE_QUIT above and before the if statement + // below -- it's possible, but unlikely. In any case, we should + // probably let the catch code throw the exception because we don't + // want to skip that and potentially run some other code. For + // example, an error may have originally brought us here for some + // cleanup operation and we shouldn't skip that. + + if (octave_interrupt_immediately || octave_interrupt_state < 0) return; tree_statement_list *list = static_cast (ptr); Index: src/sighandlers.cc =================================================================== RCS file: /usr/local/cvsroot/octave/src/sighandlers.cc,v retrieving revision 1.80 diff -u -r1.80 sighandlers.cc --- src/sighandlers.cc 20 Feb 2004 18:02:59 -0000 1.80 +++ src/sighandlers.cc 20 Feb 2004 20:52:03 -0000 at @ -237,7 +237,7 @@ // XXX FIXME XXX -- will setting octave_interrupt_state really help // here? - if (can_interrupt) + if (can_interrupt && octave_interrupt_state >= 0) octave_interrupt_state++; SIGHANDLER_RETURN (0); at @ -334,6 +334,13 @@ octave_jump_to_enclosing_context (); else { + // If we are already cleaning up from a previous interrupt, + // take note of the fact that another interrupt signal has + // arrived. + + if (octave_interrupt_state < 0) + octave_interrupt_state = 0; + octave_interrupt_state++; if (interactive && octave_interrupt_state == 2) at @ -363,7 +370,7 @@ // XXX FIXME XXX -- will setting octave_interrupt_state really help // here? - if (pipe_handler_error_count > 100) + if (pipe_handler_error_count > 100 && octave_interrupt_state >= 0) octave_interrupt_state++; SIGHANDLER_RETURN (0); ------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. Octave's home on the web: http://www.octave.org How to fund new projects: http://www.octave.org/funding.html Subscription information: http://www.octave.org/archive.html -------------------------------------------------------------