3Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
4 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
6This file is part of Octave.
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
37#include "oct-syscalls.h"
49#include "sighandlers.h"
56// Nonzero means we have already printed a message for this series of
57// SIGPIPES. We assume that the writer will eventually give up.
58int pipe_handler_error_count = 0;
60// TRUE means we can be interrupted.
61bool can_interrupt = false;
63// TRUE means we should try to enter the debugger on SIGINT.
64static bool Vdebug_on_interrupt = false;
66// Allow users to avoid writing octave-core for SIGHUP (sent by
67// closing gnome-terminal, for example). Note that this variable has
68// no effect if Vcrash_dumps_octave_core is FALSE.
69static bool Vsighup_dumps_octave_core = true;
71// Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
72static bool Vsigterm_dumps_octave_core = true;
75#define MAYBE_ACK_SIGNAL(sig) \
76 octave_set_signal_handler (sig, SIG_ACK)
79#define MAYBE_ACK_SIGNAL(sig) \
83// List of signals we have caught since last call to octave_signal_handler.
84static bool octave_signals_caught[NSIG];
86// Called from octave_quit () to actually do something about the signals
90octave_signal_handler (void)
92 // The list of signals is relatively short, so we will just go
93 // linearly through the list.
95 for (int i = 0; i < NSIG; i++)
97 if (octave_signals_caught[i])
99 octave_signals_caught[i] = false;
105 octave_child_list::reap ();
110 std::cerr << "warning: floating point exception -- trying to return to prompt" << std::endl;
115 std::cerr << "warning: broken pipe -- some output may be lost" << std::endl;
124my_friendly_exit (const char *sig_name, int sig_number,
125 bool save_vars = true)
127 static bool been_there_done_that = false;
129 if (been_there_done_that)
132 octave_set_signal_handler (SIGABRT, SIG_DFL);
135 std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";
137 MINGW_SIGNAL_CLEANUP ();
143 been_there_done_that = true;
145 std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
152 MINGW_SIGNAL_CLEANUP ();
158 octave_set_signal_handler (sig_number, SIG_DFL);
160#if defined (HAVE_RAISE)
162#elif defined (HAVE_KILL)
163 kill (getpid (), sig_number);
173octave_set_signal_handler (int sig, sig_handler *handler,
174 bool restart_syscalls)
176 struct sigaction act, oact;
178 act.sa_handler = handler;
183#if defined (SA_INTERRUPT)
184 act.sa_flags |= SA_INTERRUPT;
187#if defined (SA_RESTART)
188 // FIXME -- Do we also need to explicitly disable SA_RESTART?
189 else if (restart_syscalls)
190 act.sa_flags |= SA_RESTART;
193 sigemptyset (&act.sa_mask);
194 sigemptyset (&oact.sa_mask);
196 sigaction (sig, &act, &oact);
198 return oact.sa_handler;
202generic_sig_handler (int sig)
204 my_friendly_exit (strsignal (sig), sig);
211sigchld_handler (int /* sig */)
213 volatile octave_interrupt_handler saved_interrupt_handler
214 = octave_ignore_interrupts ();
216 // I wonder if this is really right, or if SIGCHLD should just be
217 // blocked on OS/2 systems the same as for systems with POSIX signal
221 volatile sig_handler *saved_sigchld_handler
222 = octave_set_signal_handler (SIGCHLD, SIG_IGN);
227 BLOCK_CHILD (set, oset);
229 if (octave_child_list::wait ())
231 // The status of some child changed.
233 octave_signal_caught = 1;
235 octave_signals_caught[SIGCHLD] = true;
238 octave_set_interrupt_handler (saved_interrupt_handler);
240 UNBLOCK_CHILD (oset);
243 octave_set_signal_handler (SIGCHLD, saved_sigchld_handler);
246 MAYBE_ACK_SIGNAL (SIGCHLD);
248#endif /* defined(SIGCHLD) */
251#if defined (__alpha__)
253sigfpe_handler (int /* sig */)
255 MAYBE_ACK_SIGNAL (SIGFPE);
257 if (can_interrupt && octave_interrupt_state >= 0)
259 octave_signal_caught = 1;
261 octave_signals_caught[SIGFPE] = true;
263 octave_interrupt_state++;
266#endif /* defined(__alpha__) */
267#endif /* defined(SIGFPE) */
269#if defined (SIGHUP) || defined (SIGTERM)
271sig_hup_or_term_handler (int sig)
273 MAYBE_ACK_SIGNAL (sig);
280 if (Vsighup_dumps_octave_core)
289 if (Vsigterm_dumps_octave_core)
299 clean_up_and_exit (0);
304#if defined (SIGWINCH)
306sigwinch_handler (int /* sig */)
308 MAYBE_ACK_SIGNAL (SIGWINCH);
310 command_editor::resize_terminal ();
315// Handle SIGINT by restarting the parser (see octave.cc).
317// This also has to work for SIGBREAK (on systems that have it), so we
318// use the value of sig, instead of just assuming that it is called
322user_abort (const char *sig_name, int sig_number)
324 if (! octave_initialized)
329 if (Vdebug_on_interrupt)
331 if (! octave_debug_on_interrupt_state)
333 tree_evaluator::debug_mode = true;
334 octave_debug_on_interrupt_state = true;
340 // Clear the flag and do normal interrupt stuff.
342 tree_evaluator::debug_mode
343 = bp_table::have_breakpoints () || Vdebugging;
344 octave_debug_on_interrupt_state = false;
348 if (octave_interrupt_immediately)
350 if (octave_interrupt_state == 0)
351 octave_interrupt_state = 1;
353 octave_jump_to_enclosing_context ();
357 // If we are already cleaning up from a previous interrupt,
358 // take note of the fact that another interrupt signal has
361 if (octave_interrupt_state < 0)
362 octave_interrupt_state = 0;
364 octave_signal_caught = 1;
365 octave_interrupt_state++;
367 if (interactive && octave_interrupt_state == 2)
368 std::cerr << "Press Control-C again to abort." << std::endl;
370 if (octave_interrupt_state >= 3)
371 my_friendly_exit (sig_name, sig_number, true);
378sigint_handler (int sig)
380 MAYBE_ACK_SIGNAL (sig);
383 if (w32_in_main_thread ())
384 user_abort (strsignal (sig), sig);
388 user_abort (strsignal (sig), sig);
394sigpipe_handler (int /* sig */)
396 MAYBE_ACK_SIGNAL (SIGPIPE);
398 octave_signal_caught = 1;
400 octave_signals_caught[SIGPIPE] = true;
402 // Don't loop forever on account of this.
404 if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
405 octave_interrupt_state++;
407#endif /* defined(SIGPIPE) */
411w32_sigint_handler (DWORD sig)
413 const char *sig_name;
417 case CTRL_BREAK_EVENT:
418 sig_name = "Ctrl-Break";
423 case CTRL_CLOSE_EVENT:
424 sig_name = "close console";
426 case CTRL_LOGOFF_EVENT:
429 case CTRL_SHUTDOWN_EVENT:
430 sig_name = "shutdown";
433 sig_name = "unknown console event";
439 case CTRL_BREAK_EVENT:
444 case CTRL_CLOSE_EVENT:
445 case CTRL_LOGOFF_EVENT:
446 case CTRL_SHUTDOWN_EVENT:
448 // We should do the following:
449 // clean_up_and_exit (0);
450 // We can't because we aren't running in the normal Octave thread.
451 user_abort(sig_name, sig);
455 // Return TRUE if the event was handled, or FALSE if another handler
457 // FIXME check that windows terminates the thread.
460#endif /* w32_sigint_handler */
463octave_interrupt_handler
464octave_catch_interrupts (void)
466 octave_interrupt_handler retval;
469 retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
473 retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
478 // Intercept windows console control events.
479 // Note that the windows console signal handlers chain, so if
480 // install_signal_handlers is called more than once in the same program,
481 // then first call the following to avoid duplicates:
483 // SetConsoleCtrlHandler (w32_sigint_handler, FALSE);
485 if (! SetConsoleCtrlHandler (w32_sigint_handler, TRUE))
486 error ("SetConsoleCtrlHandler failed with %ld\n", GetLastError ());
488 w32_set_quiet_shutdown ();
495octave_interrupt_handler
496octave_ignore_interrupts (void)
498 octave_interrupt_handler retval;
501 retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
505 retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
511octave_interrupt_handler
512octave_set_interrupt_handler (const volatile octave_interrupt_handler& h,
513 bool restart_syscalls)
515 octave_interrupt_handler retval;
518 retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
523 retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
530// Install all the handlers for the signals we might care about.
533install_signal_handlers (void)
535 for (int i = 0; i < NSIG; i++)
536 octave_signals_caught[i] = false;
538 octave_catch_interrupts ();
541 octave_set_signal_handler (SIGABRT, generic_sig_handler);
545 octave_set_signal_handler (SIGALRM, generic_sig_handler);
549 octave_set_signal_handler (SIGBUS, generic_sig_handler);
553 octave_set_signal_handler (SIGCHLD, sigchld_handler);
560 octave_set_signal_handler (SIGEMT, generic_sig_handler);
564#if defined (__alpha__)
565 octave_set_signal_handler (SIGFPE, sigfpe_handler);
567 octave_set_signal_handler (SIGFPE, generic_sig_handler);
572 octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
576 octave_set_signal_handler (SIGILL, generic_sig_handler);
583 octave_set_signal_handler (SIGIOT, generic_sig_handler);
587 octave_set_signal_handler (SIGLOST, generic_sig_handler);
591 octave_set_signal_handler (SIGPIPE, sigpipe_handler);
595 octave_set_signal_handler (SIGPOLL, SIG_IGN);
602 octave_set_signal_handler (SIGQUIT, generic_sig_handler);
606 octave_set_signal_handler (SIGSEGV, generic_sig_handler);
612 octave_set_signal_handler (SIGSYS, generic_sig_handler);
616 octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
620 octave_set_signal_handler (SIGTRAP, generic_sig_handler);
629 octave_set_signal_handler (SIGUSR1, generic_sig_handler);
633 octave_set_signal_handler (SIGUSR2, generic_sig_handler);
637 octave_set_signal_handler (SIGVTALRM, generic_sig_handler);
641 octave_set_signal_handler (SIGIO, SIG_IGN);
646 octave_set_signal_handler (SIGWINCH, sigwinch_handler);
651 octave_set_signal_handler (SIGXCPU, generic_sig_handler);
655 octave_set_signal_handler (SIGXFSZ, generic_sig_handler);
661make_sig_struct (void)
666 m.assign ("ABRT", SIGABRT);
670 m.assign ("ALRM", SIGALRM);
674 m.assign ("BUS", SIGBUS);
678 m.assign ("CHLD", SIGCHLD);
682 m.assign ("CLD", SIGCLD);
686 m.assign ("CONT", SIGCONT);
690 m.assign ("EMT", SIGEMT);
694 m.assign ("FPE", SIGFPE);
698 m.assign ("HUP", SIGHUP);
702 m.assign ("ILL", SIGILL);
706 m.assign ("INFO", SIGINFO);
710 m.assign ("INT", SIGINT);
714 m.assign ("IOT", SIGIOT);
718 m.assign ("LOST", SIGLOST);
722 m.assign ("PIPE", SIGPIPE);
726 m.assign ("POLL", SIGPOLL);
730 m.assign ("PROF", SIGPROF);
734 m.assign ("PWR", SIGPWR);
738 m.assign ("QUIT", SIGQUIT);
742 m.assign ("SEGV", SIGSEGV);
746 m.assign ("STOP", SIGSTOP);
750 m.assign ("SYS", SIGSYS);
754 m.assign ("TERM", SIGTERM);
758 m.assign ("TRAP", SIGTRAP);
762 m.assign ("TSTP", SIGTSTP);
766 m.assign ("TTIN", SIGTTIN);
770 m.assign ("TTOU", SIGTTOU);
774 m.assign ("URG", SIGURG);
778 m.assign ("USR1", SIGUSR1);
782 m.assign ("USR2", SIGUSR2);
786 m.assign ("VTALRM", SIGVTALRM);
790 m.assign ("IO", SIGIO);
794 m.assign ("WINCH", SIGWINCH);
798 m.assign ("XCPU", SIGXCPU);
802 m.assign ("XFSZ", SIGXFSZ);
808octave_child_list::octave_child_list_rep *octave_child_list::instance = 0;
811octave_child_list::instance_ok (void)
816 instance = new octave_child_list_rep ();
820 ::error ("unable to create child list object!");
829octave_child_list::insert (pid_t pid, octave_child::child_event_handler f)
832 instance->insert (pid, f);
836octave_child_list::reap (void)
843octave_child_list::wait (void)
845 return (instance_ok ()) ? instance->wait () : false;
852 pid_equal (pid_t v) : val (v) { }
854 bool operator () (const octave_child& oc) const { return oc.pid == val; }
862octave_child_list::remove (pid_t pid)
865 instance->remove_if (pid_equal (pid));
868#define OCL_REP octave_child_list::octave_child_list_rep
871OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
873 append (octave_child (pid, f));
879 // Mark the record for PID invalid.
881 for (iterator p = begin (); p != end (); p++)
883 // The call to the octave_child::child_event_handler might
884 // invalidate the iterator (for example, by calling
885 // octave_child_list::remove), so we increment the iterator
888 octave_child& oc = *p;
894 octave_child::child_event_handler f = oc.handler;
896 if (f && f (oc.pid, oc.status))
901 remove_if (pid_equal (-1));
904// Wait on our children and record any changes in their status.
911 for (iterator p = begin (); p != end (); p++)
913 octave_child& oc = *p;
921 if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
939@deftypefn {Built-in Function} {} SIG ()\n\
940Return a structure containing Unix signal names and their defined values.\n\
945 if (args.length () == 0)
947 static Octave_map m = make_sig_struct ();
957DEFUN (debug_on_interrupt, args, nargout,
959@deftypefn {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
960@deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\
961Query or set the internal variable that controls whether Octave will try\n\
962to enter debugging mode when it receives an interrupt signal (typically\n\
963generated with @kbd{C-c}). If a second interrupt signal is received\n\
964before reaching the debugging mode, a normal interrupt will occur.\n\
967 return SET_INTERNAL_VARIABLE (debug_on_interrupt);
970DEFUN (sighup_dumps_octave_core, args, nargout,
972@deftypefn {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
973@deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\
974Query or set the internal variable that controls whether Octave tries\n\
975to save all current variables to the file \"octave-core\" if it receives\n\
979 return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
982DEFUN (sigterm_dumps_octave_core, args, nargout,
984@deftypefn {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
985@deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\
986Query or set the internal variable that controls whether Octave tries\n\
987to save all current variables to the file \"octave-core\" if it receives\n\
988a terminate signal.\n\
991 return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);