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/>.
34#ifdef HAVE_SYS_TYPES_H
41#include "oct-syscalls.h"
52#include "sighandlers.h"
59// Nonzero means we have already printed a message for this series of
60// SIGPIPES. We assume that the writer will eventually give up.
61int pipe_handler_error_count = 0;
63// TRUE means we can be interrupted.
64bool can_interrupt = false;
66// TRUE means we should try to enter the debugger on SIGINT.
67static bool Vdebug_on_interrupt = false;
69// Allow users to avoid writing octave-core for SIGHUP (sent by
70// closing gnome-terminal, for example). Note that this variable has
71// no effect if Vcrash_dumps_octave_core is FALSE.
72static bool Vsighup_dumps_octave_core = true;
74// Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
75static bool Vsigterm_dumps_octave_core = true;
77#if defined (RETSIGTYPE_IS_VOID)
78#define SIGHANDLER_RETURN(status) return
80#define SIGHANDLER_RETURN(status) return status
83#if defined (MUST_REINSTALL_SIGHANDLERS)
84#define MAYBE_REINSTALL_SIGHANDLER(sig, handler) \
85 octave_set_signal_handler (sig, handler)
86#define REINSTALL_USES_SIG 1
88#define MAYBE_REINSTALL_SIGHANDLER(sig, handler) \
93#define MAYBE_ACK_SIGNAL(sig) \
94 octave_set_signal_handler (sig, SIG_ACK)
97#define MAYBE_ACK_SIGNAL(sig) \
101// List of signals we have caught since last call to octave_signal_handler.
102static bool octave_signals_caught[NSIG];
104// Called from OCTAVE_QUIT to actually do something about the signals
108octave_signal_handler (void)
110 // The list of signals is relatively short, so we will just go
111 // linearly through the list.
113 for (int i = 0; i < NSIG; i++)
115 if (octave_signals_caught[i])
117 octave_signals_caught[i] = false;
123 octave_child_list::reap ();
128 std::cerr << "warning: floating point exception -- trying to return to prompt" << std::endl;
133 std::cerr << "warning: broken pipe -- some output may be lost" << std::endl;
142my_friendly_exit (const char *sig_name, int sig_number,
143 bool save_vars = true)
145 static bool been_there_done_that = false;
147 if (been_there_done_that)
150 octave_set_signal_handler (SIGABRT, SIG_DFL);
153 std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";
155 MINGW_SIGNAL_CLEANUP ();
161 been_there_done_that = true;
163 std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
170 MINGW_SIGNAL_CLEANUP ();
176 octave_set_signal_handler (sig_number, SIG_DFL);
178#if defined (HAVE_RAISE)
180#elif defined (HAVE_KILL)
181 kill (getpid (), sig_number);
191octave_set_signal_handler (int sig, sig_handler *handler,
192 bool restart_syscalls)
194#if defined (HAVE_POSIX_SIGNALS)
195 struct sigaction act, oact;
197 act.sa_handler = handler;
202#if defined (SA_INTERRUPT)
203 act.sa_flags |= SA_INTERRUPT;
206#if defined (SA_RESTART)
207 // FIXME -- Do we also need to explicitly disable SA_RESTART?
208 else if (restart_syscalls)
209 act.sa_flags |= SA_RESTART;
212 sigemptyset (&act.sa_mask);
213 sigemptyset (&oact.sa_mask);
215 sigaction (sig, &act, &oact);
217 return oact.sa_handler;
219 return signal (sig, handler);
224generic_sig_handler (int sig)
226 my_friendly_exit (strsignal (sig), sig);
228 SIGHANDLER_RETURN (0);
235sigchld_handler (int /* sig */)
237 volatile octave_interrupt_handler saved_interrupt_handler
238 = octave_ignore_interrupts ();
240 // I wonder if this is really right, or if SIGCHLD should just be
241 // blocked on OS/2 systems the same as for systems with POSIX signal
245 volatile sig_handler *saved_sigchld_handler
246 = octave_set_signal_handler (SIGCHLD, SIG_IGN);
251 BLOCK_CHILD (set, oset);
253 if (octave_child_list::wait ())
255 // The status of some child changed.
257 octave_signal_caught = 1;
259 octave_signals_caught[SIGCHLD] = true;
262 octave_set_interrupt_handler (saved_interrupt_handler);
264 UNBLOCK_CHILD (oset);
267 octave_set_signal_handler (SIGCHLD, saved_sigchld_handler);
270 MAYBE_ACK_SIGNAL (SIGCHLD);
272 MAYBE_REINSTALL_SIGHANDLER (SIGCHLD, sigchld_handler);
274 SIGHANDLER_RETURN (0);
276#endif /* defined(SIGCHLD) */
279#if defined (__alpha__)
281sigfpe_handler (int /* sig */)
283 MAYBE_ACK_SIGNAL (SIGFPE);
285 MAYBE_REINSTALL_SIGHANDLER (SIGFPE, sigfpe_handler);
287 if (can_interrupt && octave_interrupt_state >= 0)
289 octave_signal_caught = 1;
291 octave_signals_caught[SIGFPE] = true;
293 octave_interrupt_state++;
296 SIGHANDLER_RETURN (0);
298#endif /* defined(__alpha__) */
299#endif /* defined(SIGFPE) */
301#if defined (SIGHUP) || defined (SIGTERM)
303sig_hup_or_term_handler (int sig)
305 MAYBE_ACK_SIGNAL (sig);
307 MAYBE_REINSTALL_SIGHANDLER (sig, sig_hup_or_term_handler);
314 if (Vsighup_dumps_octave_core)
323 if (Vsigterm_dumps_octave_core)
333 clean_up_and_exit (0);
335 SIGHANDLER_RETURN (0);
340#if defined (SIGWINCH)
342sigwinch_handler (int /* sig */)
344 MAYBE_ACK_SIGNAL (SIGWINCH);
346 MAYBE_REINSTALL_SIGHANDLER (SIGWINCH, sigwinch_handler);
348 command_editor::resize_terminal ();
350 SIGHANDLER_RETURN (0);
355// Handle SIGINT by restarting the parser (see octave.cc).
357// This also has to work for SIGBREAK (on systems that have it), so we
358// use the value of sig, instead of just assuming that it is called
362user_abort (const char *sig_name, int sig_number)
364 if (! octave_initialized)
369 if (Vdebug_on_interrupt)
371 if (! octave_debug_on_interrupt_state)
373 tree_evaluator::debug_mode = true;
374 octave_debug_on_interrupt_state = true;
380 // Clear the flag and do normal interrupt stuff.
382 tree_evaluator::debug_mode = bp_table::have_breakpoints ();
383 octave_debug_on_interrupt_state = false;
387 if (octave_interrupt_immediately)
389 if (octave_interrupt_state == 0)
390 octave_interrupt_state = 1;
392 octave_jump_to_enclosing_context ();
396 // If we are already cleaning up from a previous interrupt,
397 // take note of the fact that another interrupt signal has
400 if (octave_interrupt_state < 0)
401 octave_interrupt_state = 0;
403 octave_signal_caught = 1;
404 octave_interrupt_state++;
406 if (interactive && octave_interrupt_state == 2)
407 std::cerr << "Press Control-C again to abort." << std::endl;
409 if (octave_interrupt_state >= 3)
410 my_friendly_exit (sig_name, sig_number, true);
417sigint_handler (int sig)
419 MAYBE_ACK_SIGNAL (sig);
421 MAYBE_REINSTALL_SIGHANDLER (sig, sigint_handler);
424 if (w32_in_main_thread ())
425 user_abort (strsignal (sig), sig);
429 user_abort (strsignal (sig), sig);
432 SIGHANDLER_RETURN (0);
437sigpipe_handler (int /* sig */)
439 MAYBE_ACK_SIGNAL (SIGPIPE);
441 MAYBE_REINSTALL_SIGHANDLER (SIGPIPE, sigpipe_handler);
443 octave_signal_caught = 1;
445 octave_signals_caught[SIGPIPE] = true;
447 // Don't loop forever on account of this.
449 if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
450 octave_interrupt_state++;
452 SIGHANDLER_RETURN (0);
454#endif /* defined(SIGPIPE) */
458w32_sigint_handler (DWORD sig)
460 const char *sig_name;
464 case CTRL_BREAK_EVENT:
465 sig_name = "Ctrl-Break";
470 case CTRL_CLOSE_EVENT:
471 sig_name = "close console";
473 case CTRL_LOGOFF_EVENT:
476 case CTRL_SHUTDOWN_EVENT:
477 sig_name = "shutdown";
480 sig_name = "unknown console event";
486 case CTRL_BREAK_EVENT:
491 case CTRL_CLOSE_EVENT:
492 case CTRL_LOGOFF_EVENT:
493 case CTRL_SHUTDOWN_EVENT:
495 // We should do the following:
496 // clean_up_and_exit (0);
497 // We can't because we aren't running in the normal Octave thread.
498 user_abort(sig_name, sig);
502 // Return TRUE if the event was handled, or FALSE if another handler
504 // FIXME check that windows terminates the thread.
507#endif /* w32_sigint_handler */
510octave_interrupt_handler
511octave_catch_interrupts (void)
513 octave_interrupt_handler retval;
516 retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
520 retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
525 // Intercept windows console control events.
526 // Note that the windows console signal handlers chain, so if
527 // install_signal_handlers is called more than once in the same program,
528 // then first call the following to avoid duplicates:
530 // SetConsoleCtrlHandler (w32_sigint_handler, FALSE);
532 if (! SetConsoleCtrlHandler (w32_sigint_handler, TRUE))
533 error ("SetConsoleCtrlHandler failed with %ld\n", GetLastError ());
535 w32_set_quiet_shutdown ();
542octave_interrupt_handler
543octave_ignore_interrupts (void)
545 octave_interrupt_handler retval;
548 retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
552 retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
558octave_interrupt_handler
559octave_set_interrupt_handler (const volatile octave_interrupt_handler& h,
560 bool restart_syscalls)
562 octave_interrupt_handler retval;
565 retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
570 retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
577// Install all the handlers for the signals we might care about.
580install_signal_handlers (void)
582 for (int i = 0; i < NSIG; i++)
583 octave_signals_caught[i] = false;
585 octave_catch_interrupts ();
588 octave_set_signal_handler (SIGABRT, generic_sig_handler);
592 octave_set_signal_handler (SIGALRM, generic_sig_handler);
596 octave_set_signal_handler (SIGBUS, generic_sig_handler);
600 octave_set_signal_handler (SIGCHLD, sigchld_handler);
607 octave_set_signal_handler (SIGEMT, generic_sig_handler);
611#if defined (__alpha__)
612 octave_set_signal_handler (SIGFPE, sigfpe_handler);
614 octave_set_signal_handler (SIGFPE, generic_sig_handler);
619 octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
623 octave_set_signal_handler (SIGILL, generic_sig_handler);
630 octave_set_signal_handler (SIGIOT, generic_sig_handler);
634 octave_set_signal_handler (SIGLOST, generic_sig_handler);
638 octave_set_signal_handler (SIGPIPE, sigpipe_handler);
642 octave_set_signal_handler (SIGPOLL, SIG_IGN);
649 octave_set_signal_handler (SIGQUIT, generic_sig_handler);
653 octave_set_signal_handler (SIGSEGV, generic_sig_handler);
659 octave_set_signal_handler (SIGSYS, generic_sig_handler);
663 octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
667 octave_set_signal_handler (SIGTRAP, generic_sig_handler);
676 octave_set_signal_handler (SIGUSR1, generic_sig_handler);
680 octave_set_signal_handler (SIGUSR2, generic_sig_handler);
684 octave_set_signal_handler (SIGVTALRM, generic_sig_handler);
688 octave_set_signal_handler (SIGIO, SIG_IGN);
693 octave_set_signal_handler (SIGWINCH, sigwinch_handler);
698 octave_set_signal_handler (SIGXCPU, generic_sig_handler);
702 octave_set_signal_handler (SIGXFSZ, generic_sig_handler);
708make_sig_struct (void)
713 m.assign ("ABRT", SIGABRT);
717 m.assign ("ALRM", SIGALRM);
721 m.assign ("BUS", SIGBUS);
725 m.assign ("CHLD", SIGCHLD);
729 m.assign ("CLD", SIGCLD);
733 m.assign ("CONT", SIGCONT);
737 m.assign ("EMT", SIGEMT);
741 m.assign ("FPE", SIGFPE);
745 m.assign ("HUP", SIGHUP);
749 m.assign ("ILL", SIGILL);
753 m.assign ("INFO", SIGINFO);
757 m.assign ("INT", SIGINT);
761 m.assign ("IOT", SIGIOT);
765 m.assign ("LOST", SIGLOST);
769 m.assign ("PIPE", SIGPIPE);
773 m.assign ("POLL", SIGPOLL);
777 m.assign ("PROF", SIGPROF);
781 m.assign ("PWR", SIGPWR);
785 m.assign ("QUIT", SIGQUIT);
789 m.assign ("SEGV", SIGSEGV);
793 m.assign ("STOP", SIGSTOP);
797 m.assign ("SYS", SIGSYS);
801 m.assign ("TERM", SIGTERM);
805 m.assign ("TRAP", SIGTRAP);
809 m.assign ("TSTP", SIGTSTP);
813 m.assign ("TTIN", SIGTTIN);
817 m.assign ("TTOU", SIGTTOU);
821 m.assign ("URG", SIGURG);
825 m.assign ("USR1", SIGUSR1);
829 m.assign ("USR2", SIGUSR2);
833 m.assign ("VTALRM", SIGVTALRM);
837 m.assign ("IO", SIGIO);
841 m.assign ("WINCH", SIGWINCH);
845 m.assign ("XCPU", SIGXCPU);
849 m.assign ("XFSZ", SIGXFSZ);
855octave_child_list::octave_child_list_rep *octave_child_list::instance = 0;
858octave_child_list::instance_ok (void)
863 instance = new octave_child_list_rep ();
867 ::error ("unable to create child list object!");
876octave_child_list::insert (pid_t pid, octave_child::child_event_handler f)
879 instance->insert (pid, f);
883octave_child_list::reap (void)
890octave_child_list::wait (void)
892 return (instance_ok ()) ? instance->wait () : false;
899 pid_equal (pid_t v) : val (v) { }
901 bool operator () (const octave_child& oc) const { return oc.pid == val; }
909octave_child_list::remove (pid_t pid)
912 instance->remove_if (pid_equal (pid));
915#define OCL_REP octave_child_list::octave_child_list_rep
918OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
920 append (octave_child (pid, f));
926 // Mark the record for PID invalid.
928 for (iterator p = begin (); p != end (); p++)
930 // The call to the octave_child::child_event_handler might
931 // invalidate the iterator (for example, by calling
932 // octave_child_list::remove), so we increment the iterator
935 octave_child& oc = *p;
941 octave_child::child_event_handler f = oc.handler;
943 if (f && f (oc.pid, oc.status))
948 remove_if (pid_equal (-1));
951// Wait on our children and record any changes in their status.
958 for (iterator p = begin (); p != end (); p++)
960 octave_child& oc = *p;
968 if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
986@deftypefn {Built-in Function} {} SIG ()\n\
987Return a structure containing Unix signal names and their defined values.\n\
992 if (args.length () == 0)
994 static Octave_map m = make_sig_struct ();
1004DEFUN (debug_on_interrupt, args, nargout,
1006@deftypefn {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
1007@deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\
1008Query or set the internal variable that controls whether Octave will try\n\
1009to enter debugging mode when it receives an interrupt signal (typically\n\
1010generated with @kbd{C-c}). If a second interrupt signal is received\n\
1011before reaching the debugging mode, a normal interrupt will occur.\n\
1014 return SET_INTERNAL_VARIABLE (debug_on_interrupt);
1017DEFUN (sighup_dumps_octave_core, args, nargout,
1019@deftypefn {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
1020@deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\
1021Query or set the internal variable that controls whether Octave tries\n\
1022to save all current variables to the file \"octave-core\" if it receives\n\
1026 return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
1029DEFUN (sigterm_dumps_octave_core, args, nargout,
1031@deftypefn {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
1032@deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\
1033Query or set the internal variable that controls whether Octave tries\n\
1034to save all current variables to the file \"octave-core\" if it receives\n\
1035a terminate signal.\n\
1038 return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
1042;;; Local Variables: ***