Mercurial > octave
comparison 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 |
comparison
equal
deleted
inserted
replaced
24519:6c31b0376908 | 24520:c5c11b07598a |
---|---|
193 | 193 |
194 bool do_prefer_env_winsize (bool); | 194 bool do_prefer_env_winsize (bool); |
195 | 195 |
196 void do_interrupt (bool); | 196 void do_interrupt (bool); |
197 | 197 |
198 void do_handle_interrupt_signal (void); | |
199 | |
198 static int operate_and_get_next (int, int); | 200 static int operate_and_get_next (int, int); |
199 | 201 |
200 static int history_search_backward (int, int); | 202 static int history_search_backward (int, int); |
201 | 203 |
202 static int history_search_forward (int, int); | 204 static int history_search_forward (int, int); |
285 | 287 |
286 eof = false; | 288 eof = false; |
287 | 289 |
288 const char *p = prompt.c_str (); | 290 const char *p = prompt.c_str (); |
289 | 291 |
290 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 292 while (true) |
291 | 293 { |
292 char *line = ::octave_rl_readline (p); | 294 try |
293 | 295 { |
294 if (line) | 296 char *line = ::octave_rl_readline (p); |
295 { | 297 |
296 retval = line; | 298 if (line) |
297 | 299 { |
298 free (line); | 300 retval = line; |
299 } | 301 |
300 else | 302 free (line); |
301 eof = true; | 303 } |
302 | 304 else |
303 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 305 eof = true; |
306 | |
307 break; | |
308 } | |
309 catch (command_editor::interrupt_exception&) | |
310 { | |
311 // Is this right? | |
312 std::cout << "\n"; | |
313 | |
314 // Try again... | |
315 } | |
316 } | |
304 | 317 |
305 return retval; | 318 return retval; |
306 } | 319 } |
307 | 320 |
308 void | 321 void |
780 gnu_readline::do_interrupt (bool arg) | 793 gnu_readline::do_interrupt (bool arg) |
781 { | 794 { |
782 ::octave_rl_done (arg); | 795 ::octave_rl_done (arg); |
783 } | 796 } |
784 | 797 |
798 void | |
799 gnu_readline::do_handle_interrupt_signal (void) | |
800 { | |
801 octave_signal_caught = 0; | |
802 octave_interrupt_state = 0; | |
803 | |
804 ::octave_rl_recover_from_interrupt (); | |
805 | |
806 throw command_editor::interrupt_exception (); | |
807 } | |
808 | |
785 int | 809 int |
786 gnu_readline::operate_and_get_next (int /* count */, int /* c */) | 810 gnu_readline::operate_and_get_next (int /* count */, int /* c */) |
787 { | 811 { |
788 // Accept the current line. | 812 // Accept the current line. |
789 | 813 |
1062 if (! instance) | 1086 if (! instance) |
1063 { | 1087 { |
1064 make_command_editor (); | 1088 make_command_editor (); |
1065 | 1089 |
1066 if (instance) | 1090 if (instance) |
1067 singleton_cleanup_list::add (cleanup_instance); | 1091 { |
1092 instance->set_event_hook (event_handler); | |
1093 | |
1094 singleton_cleanup_list::add (cleanup_instance); | |
1095 } | |
1068 } | 1096 } |
1069 | 1097 |
1070 if (! instance) | 1098 if (! instance) |
1071 (*current_liboctave_error_handler) | 1099 (*current_liboctave_error_handler) |
1072 ("unable to create command history object!"); | 1100 ("unable to create command history object!"); |
1129 } | 1157 } |
1130 | 1158 |
1131 int | 1159 int |
1132 command_editor::event_handler (void) | 1160 command_editor::event_handler (void) |
1133 { | 1161 { |
1162 if (octave_interrupt_state) | |
1163 handle_interrupt_signal (); | |
1164 | |
1134 event_hook_lock.lock (); | 1165 event_hook_lock.lock (); |
1135 | 1166 |
1136 std::set<event_hook_fcn> hook_set (event_hook_set); | 1167 std::set<event_hook_fcn> hook_set (event_hook_set); |
1137 | 1168 |
1138 event_hook_lock.unlock (); | 1169 event_hook_lock.unlock (); |
1537 void | 1568 void |
1538 command_editor::add_event_hook (event_hook_fcn f) | 1569 command_editor::add_event_hook (event_hook_fcn f) |
1539 { | 1570 { |
1540 autolock guard (event_hook_lock); | 1571 autolock guard (event_hook_lock); |
1541 | 1572 |
1542 if (instance_ok ()) | 1573 event_hook_set.insert (f); |
1543 { | |
1544 event_hook_set.insert (f); | |
1545 | |
1546 instance->set_event_hook (event_handler); | |
1547 } | |
1548 } | 1574 } |
1549 | 1575 |
1550 void | 1576 void |
1551 command_editor::remove_event_hook (event_hook_fcn f) | 1577 command_editor::remove_event_hook (event_hook_fcn f) |
1552 { | 1578 { |
1553 autolock guard (event_hook_lock); | 1579 autolock guard (event_hook_lock); |
1554 | 1580 |
1555 if (instance_ok ()) | 1581 auto p = event_hook_set.find (f); |
1556 { | 1582 |
1557 auto p = event_hook_set.find (f); | 1583 if (p != event_hook_set.end ()) |
1558 | 1584 event_hook_set.erase (p); |
1559 if (p != event_hook_set.end ()) | 1585 |
1560 event_hook_set.erase (p); | |
1561 | |
1562 if (event_hook_set.empty ()) | |
1563 instance->restore_event_hook (); | |
1564 } | |
1565 } | 1586 } |
1566 | 1587 |
1567 void | 1588 void |
1568 command_editor::run_event_hooks (void) | 1589 command_editor::run_event_hooks (void) |
1569 { | 1590 { |
1625 } | 1646 } |
1626 else | 1647 else |
1627 retval = false; | 1648 retval = false; |
1628 | 1649 |
1629 return retval; | 1650 return retval; |
1651 } | |
1652 | |
1653 void | |
1654 command_editor::handle_interrupt_signal (void) | |
1655 { | |
1656 if (instance_ok ()) | |
1657 instance->do_handle_interrupt_signal (); | |
1630 } | 1658 } |
1631 | 1659 |
1632 // Return a string which will be printed as a prompt. The string may | 1660 // Return a string which will be printed as a prompt. The string may |
1633 // contain special characters which are decoded as follows: | 1661 // contain special characters which are decoded as follows: |
1634 // | 1662 // |