Mercurial > octave
diff liboctave/util/cmd-edit.cc @ 24520:c5c11b07598a
refactor signal handling (bug #52757)
Given that any library code may now be multi-threaded it is not likely
to be save to jump out of a signal handler when executing a call to a
library function. We are almost assured to fail if the call to
siglongjmp occurs in a different thread from the corresponding call to
sigsetjmp.
Similarly, we should avoid calling the interrupt signal handler
function in an arbitrary thread. This is already done by default on
Windows systems. On Posix systems, we now set up a separate thread to
handle asynchronous signals (not just SIGINT). We no longer attempt
to jump out of the signal handler. Instead, we only set global status
variables and respond to them in octave_quit. This means that some
external library functions are no longer interruptible. If that
becomes important, then we will need to look for other alternatives
such as setting up worker threads that can be canceled when a SIGINT
is detected.
* sighandlers.cc (interrupt_manager, base_interrupt_manager,
w32_interrupt_manager, posix_interrupt_manager): Delete classes and
all uses.
(respond_to_pending_signals): Rename from signal_handler. Change all
uses. Take action on more signals.
(generic_sig_handler): Simply record that a signal was caught and add
it to the list of caught signals.
(deadly_sig_handler): New function.
(fpe_sig_handler): Rename from sigfpe_handler. Don't make specific to
Alpha systems. Simply warn that an exception has occurred.
(sigint_handler): Simply record that an interrupt signal was caught.
(sigterm_handler, sigpipe_handler): Delete.
(install_signal_handlers): Rework actions for various signals.
(Vsigquit_dumps_octave_core): New static variable.
(Fsigquit_dumps_octave_core): New function.
* io.txi: Document sigquit_dumps_octave_core.
* f77-fcn.h, f77-fcn.c (xSTRINGIZE, STRINGIZE, F77_XFCN_ERROR):
Delete macros.
(F77_XFCN): Don't do setjmp/longjmp exception handling.
(f77_exception_encountered): Delete global variable.
(XSTOPX): Don't set f77_exception_encountered. If message is empty,
report "unknown error in fortran subroutine".
* eigs-base.cc, gsvd.cc: Delete all direct uses of
f77_exception_encountered.
* liboctave/util/f77-extern.cc: Delete file.
* liboctave/util/module.mk: Update.
* cmd-edit.h, cmd-edit.cc (command_editor::interrupt_exception): New class.
(command_editor::handle_interrupt_signal): New static function.
(command_editor::do_handle_interrupt_signal): New virtual function.
(command_editor::event_hanlder): Call handle_interrupt_signal if
octave_interrupt_state is not zero.
(command_editor::instance_ok): Set event hook here.
(command_editor::add_event_hook): Not here.
(command_editor::remove_event_hook): Never remove event hook.
(gnu_readline::do_handle_interrupt_signal): New function.
(gnu_readline::do_readline): Retry if an interrupt exception occurs
inside readline.
* oct-rl-edit.h, oct-rl-edit.c (octave_rl_recover_from_interrupt):
New function.
* quit.h, cquit.c (current_context, octave_save_current_context,
octave_restore_current_context, octave_jump_to_enclosing_context,
octave_interrupt_immediately, octave_jmp_buf): Delete.
* quit.h: Don't include <setjmp.h>
(octave_set_current_context): Delete macro.
(octave_exit_exception_status, octave_exit_exception_safe_to_return):
Mark as deprecated.
(BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1): Delete.
(BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2): Delete.
(BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE,
END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE): Define to only create a
dummy do-while scope.
(BEGIN_INTERRUPT_WITH_EXCEPTIONS, END_INTERRUPT_WITH_EXCEPTIONS):
Define to only create a dummy scope.
* interpreter.cc (interpreter::recover_from_exception):
Don't reset octave_interrupt_immediately.
* main-cli.cc (main): Call octave_block_async_signals.
* main.in.cc (main): Call octave_block_async_signals initially.
Only in install signal handlers and unblock signals if starting
managed subprocess.
* main-window.cc (octave_interpreter::executed):
Don't unblock interrupt signals.
* signal-wrappers.h, signal-wrappers.c
(signal_watcher, octave_async_signals, block_or_unblock_signal_by_name): New static functions.
(octave_set_default_signal_handler,
octave_set_default_signal_handler_by_name,
octave_block_signal_by_name, octave_unblock_signal_by_name,
octave_create_interrupt_watcher_thread, octave_block_async_signals,
octave_unblock_async_signals): New functions.
(octave_block_interrupt_signal, octave_unblock_interrupt_signal):
Treat SIGBREAK as an interrupt signal.
(octave_block_child): Also handle SIGCLD the same as SIGCHLD.
(print_sigset, print_sigmask): New static functions.
(octave_show_sigmask): New function.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 03 Jan 2018 07:52:11 -0500 |
parents | 061a343089be |
children | 194eb4bd202b |
line wrap: on
line diff
--- a/liboctave/util/cmd-edit.cc Thu Jan 04 10:09:23 2018 -0500 +++ b/liboctave/util/cmd-edit.cc Wed Jan 03 07:52:11 2018 -0500 @@ -195,6 +195,8 @@ void do_interrupt (bool); + void do_handle_interrupt_signal (void); + static int operate_and_get_next (int, int); static int history_search_backward (int, int); @@ -287,20 +289,31 @@ const char *p = prompt.c_str (); - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - - char *line = ::octave_rl_readline (p); - - if (line) + while (true) { - retval = line; + try + { + char *line = ::octave_rl_readline (p); + + if (line) + { + retval = line; - free (line); + free (line); + } + else + eof = true; + + break; + } + catch (command_editor::interrupt_exception&) + { + // Is this right? + std::cout << "\n"; + + // Try again... + } } - else - eof = true; - - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; return retval; } @@ -782,6 +795,17 @@ ::octave_rl_done (arg); } + void + gnu_readline::do_handle_interrupt_signal (void) + { + octave_signal_caught = 0; + octave_interrupt_state = 0; + + ::octave_rl_recover_from_interrupt (); + + throw command_editor::interrupt_exception (); + } + int gnu_readline::operate_and_get_next (int /* count */, int /* c */) { @@ -1064,7 +1088,11 @@ make_command_editor (); if (instance) - singleton_cleanup_list::add (cleanup_instance); + { + instance->set_event_hook (event_handler); + + singleton_cleanup_list::add (cleanup_instance); + } } if (! instance) @@ -1131,6 +1159,9 @@ int command_editor::event_handler (void) { + if (octave_interrupt_state) + handle_interrupt_signal (); + event_hook_lock.lock (); std::set<event_hook_fcn> hook_set (event_hook_set); @@ -1539,12 +1570,7 @@ { autolock guard (event_hook_lock); - if (instance_ok ()) - { - event_hook_set.insert (f); - - instance->set_event_hook (event_handler); - } + event_hook_set.insert (f); } void @@ -1552,16 +1578,11 @@ { autolock guard (event_hook_lock); - if (instance_ok ()) - { - auto p = event_hook_set.find (f); + auto p = event_hook_set.find (f); - if (p != event_hook_set.end ()) - event_hook_set.erase (p); + if (p != event_hook_set.end ()) + event_hook_set.erase (p); - if (event_hook_set.empty ()) - instance->restore_event_hook (); - } } void @@ -1629,6 +1650,13 @@ return retval; } + void + command_editor::handle_interrupt_signal (void) + { + if (instance_ok ()) + instance->do_handle_interrupt_signal (); + } + // Return a string which will be printed as a prompt. The string may // contain special characters which are decoded as follows: //