changelog shortlog tags changeset files revisions annotate raw

src/sighandlers.cc

changeset 10289: 4b124317dc38
parent:d4f813c3f5ed
author: John W. Eaton <jwe@octave.org>
date: Tue Feb 09 20:58:55 2010 -0500 (28 minutes ago)
permissions: -rw-r--r--
description: base_properties::set_children: account for hidden children
1/*
2
3Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
4 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5
6This file is part of Octave.
7
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.
12
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
16for more details.
17
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/>.
21
22*/
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <cstdlib>
29
30#include <iostream>
31#include <new>
32
33#include <sys/types.h>
34#include <unistd.h>
35
36#include "cmd-edit.h"
37#include "oct-syscalls.h"
38#include "quit.h"
39
40#include "debug.h"
41#include "defun.h"
42#include "error.h"
43#include "input.h"
44#include "load-save.h"
45#include "oct-map.h"
46#include "pager.h"
47#include "pt-bp.h"
48#include "pt-eval.h"
49#include "sighandlers.h"
50#include "sysdep.h"
51#include "syswait.h"
52#include "toplev.h"
53#include "utils.h"
54#include "variables.h"
55
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;
59
60// TRUE means we can be interrupted.
61bool can_interrupt = false;
62
63// TRUE means we should try to enter the debugger on SIGINT.
64static bool Vdebug_on_interrupt = false;
65
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;
70
71// Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
72static bool Vsigterm_dumps_octave_core = true;
73
74#if defined (__EMX__)
75#define MAYBE_ACK_SIGNAL(sig) \
76 octave_set_signal_handler (sig, SIG_ACK)
77#define ACK_USES_SIG 1
78#else
79#define MAYBE_ACK_SIGNAL(sig) \
80 do { } while (0)
81#endif
82
83// List of signals we have caught since last call to octave_signal_handler.
84static bool octave_signals_caught[NSIG];
85
86// Called from octave_quit () to actually do something about the signals
87// we have caught.
88
89void
90octave_signal_handler (void)
91{
92 // The list of signals is relatively short, so we will just go
93 // linearly through the list.
94
95 for (int i = 0; i < NSIG; i++)
96 {
97 if (octave_signals_caught[i])
98 {
99 octave_signals_caught[i] = false;
100
101 switch (i)
102 {
103#ifdef SIGCHLD
104 case SIGCHLD:
105 octave_child_list::reap ();
106 break;
107#endif
108
109 case SIGFPE:
110 std::cerr << "warning: floating point exception -- trying to return to prompt" << std::endl;
111 break;
112
113#ifdef SIGPIPE
114 case SIGPIPE:
115 std::cerr << "warning: broken pipe -- some output may be lost" << std::endl;
116 break;
117#endif
118 }
119 }
120 }
121}
122
123static void
124my_friendly_exit (const char *sig_name, int sig_number,
125 bool save_vars = true)
126{
127 static bool been_there_done_that = false;
128
129 if (been_there_done_that)
130 {
131#if defined (SIGABRT)
132 octave_set_signal_handler (SIGABRT, SIG_DFL);
133#endif
134
135 std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";
136
137 MINGW_SIGNAL_CLEANUP ();
138
139 abort ();
140 }
141 else
142 {
143 been_there_done_that = true;
144
145 std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
146
147 if (save_vars)
148 dump_octave_core ();
149
150 if (sig_number < 0)
151 {
152 MINGW_SIGNAL_CLEANUP ();
153
154 exit (1);
155 }
156 else
157 {
158 octave_set_signal_handler (sig_number, SIG_DFL);
159
160#if defined (HAVE_RAISE)
161 raise (sig_number);
162#elif defined (HAVE_KILL)
163 kill (getpid (), sig_number);
164#else
165 exit (1);
166#endif
167 }
168
169 }
170}
171
172sig_handler *
173octave_set_signal_handler (int sig, sig_handler *handler,
174 bool restart_syscalls)
175{
176 struct sigaction act, oact;
177
178 act.sa_handler = handler;
179 act.sa_flags = 0;
180
181 if (sig == SIGALRM)
182 {
183#if defined (SA_INTERRUPT)
184 act.sa_flags |= SA_INTERRUPT;
185#endif
186 }
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;
191#endif
192
193 sigemptyset (&act.sa_mask);
194 sigemptyset (&oact.sa_mask);
195
196 sigaction (sig, &act, &oact);
197
198 return oact.sa_handler;
199}
200
201static void
202generic_sig_handler (int sig)
203{
204 my_friendly_exit (strsignal (sig), sig);
205}
206
207// Handle SIGCHLD.
208
209#ifdef SIGCHLD
210static void
211sigchld_handler (int /* sig */)
212{
213 volatile octave_interrupt_handler saved_interrupt_handler
214 = octave_ignore_interrupts ();
215
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
218 // functions.
219
220#if defined (__EMX__)
221 volatile sig_handler *saved_sigchld_handler
222 = octave_set_signal_handler (SIGCHLD, SIG_IGN);
223#endif
224
225 sigset_t set, oset;
226
227 BLOCK_CHILD (set, oset);
228
229 if (octave_child_list::wait ())
230 {
231 // The status of some child changed.
232
233 octave_signal_caught = 1;
234
235 octave_signals_caught[SIGCHLD] = true;
236 }
237
238 octave_set_interrupt_handler (saved_interrupt_handler);
239
240 UNBLOCK_CHILD (oset);
241
242#ifdef __EMX__
243 octave_set_signal_handler (SIGCHLD, saved_sigchld_handler);
244#endif
245
246 MAYBE_ACK_SIGNAL (SIGCHLD);
247}
248#endif /* defined(SIGCHLD) */
249
250#ifdef SIGFPE
251#if defined (__alpha__)
252static void
253sigfpe_handler (int /* sig */)
254{
255 MAYBE_ACK_SIGNAL (SIGFPE);
256
257 if (can_interrupt && octave_interrupt_state >= 0)
258 {
259 octave_signal_caught = 1;
260
261 octave_signals_caught[SIGFPE] = true;
262
263 octave_interrupt_state++;
264 }
265}
266#endif /* defined(__alpha__) */
267#endif /* defined(SIGFPE) */
268
269#if defined (SIGHUP) || defined (SIGTERM)
270static void
271sig_hup_or_term_handler (int sig)
272{
273 MAYBE_ACK_SIGNAL (sig);
274
275 switch (sig)
276 {
277#if defined (SIGHUP)
278 case SIGHUP:
279 {
280 if (Vsighup_dumps_octave_core)
281 dump_octave_core ();
282 }
283 break;
284#endif
285
286#if defined (SIGTERM)
287 case SIGTERM:
288 {
289 if (Vsigterm_dumps_octave_core)
290 dump_octave_core ();
291 }
292 break;
293#endif
294
295 default:
296 break;
297 }
298
299 clean_up_and_exit (0);
300}
301#endif
302
303#if 0
304#if defined (SIGWINCH)
305static void
306sigwinch_handler (int /* sig */)
307{
308 MAYBE_ACK_SIGNAL (SIGWINCH);
309
310 command_editor::resize_terminal ();
311}
312#endif
313#endif
314
315// Handle SIGINT by restarting the parser (see octave.cc).
316//
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
319// for SIGINT only.
320
321static void
322user_abort (const char *sig_name, int sig_number)
323{
324 if (! octave_initialized)
325 exit (1);
326
327 if (can_interrupt)
328 {
329 if (Vdebug_on_interrupt)
330 {
331 if (! octave_debug_on_interrupt_state)
332 {
333 tree_evaluator::debug_mode = true;
334 octave_debug_on_interrupt_state = true;
335
336 return;
337 }
338 else
339 {
340 // Clear the flag and do normal interrupt stuff.
341
342 tree_evaluator::debug_mode
343 = bp_table::have_breakpoints () || Vdebugging;
344 octave_debug_on_interrupt_state = false;
345 }
346 }
347
348 if (octave_interrupt_immediately)
349 {
350 if (octave_interrupt_state == 0)
351 octave_interrupt_state = 1;
352
353 octave_jump_to_enclosing_context ();
354 }
355 else
356 {
357 // If we are already cleaning up from a previous interrupt,
358 // take note of the fact that another interrupt signal has
359 // arrived.
360
361 if (octave_interrupt_state < 0)
362 octave_interrupt_state = 0;
363
364 octave_signal_caught = 1;
365 octave_interrupt_state++;
366
367 if (interactive && octave_interrupt_state == 2)
368 std::cerr << "Press Control-C again to abort." << std::endl;
369
370 if (octave_interrupt_state >= 3)
371 my_friendly_exit (sig_name, sig_number, true);
372 }
373 }
374
375}
376
377static void
378sigint_handler (int sig)
379{
380 MAYBE_ACK_SIGNAL (sig);
381
382#ifdef USE_W32_SIGINT
383 if (w32_in_main_thread ())
384 user_abort (strsignal (sig), sig);
385 else
386 w32_raise (sig);
387#else
388 user_abort (strsignal (sig), sig);
389#endif
390}
391
392#ifdef SIGPIPE
393static void
394sigpipe_handler (int /* sig */)
395{
396 MAYBE_ACK_SIGNAL (SIGPIPE);
397
398 octave_signal_caught = 1;
399
400 octave_signals_caught[SIGPIPE] = true;
401
402 // Don't loop forever on account of this.
403
404 if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
405 octave_interrupt_state++;
406}
407#endif /* defined(SIGPIPE) */
408
409#ifdef USE_W32_SIGINT
410static BOOL CALLBACK
411w32_sigint_handler (DWORD sig)
412{
413 const char *sig_name;
414
415 switch(sig)
416 {
417 case CTRL_BREAK_EVENT:
418 sig_name = "Ctrl-Break";
419 break;
420 case CTRL_C_EVENT:
421 sig_name = "Ctrl-C";
422 break;
423 case CTRL_CLOSE_EVENT:
424 sig_name = "close console";
425 break;
426 case CTRL_LOGOFF_EVENT:
427 sig_name = "logoff";
428 break;
429 case CTRL_SHUTDOWN_EVENT:
430 sig_name = "shutdown";
431 break;
432 default:
433 sig_name = "unknown console event";
434 break;
435 }
436
437 switch(sig)
438 {
439 case CTRL_BREAK_EVENT:
440 case CTRL_C_EVENT:
441 w32_raise (SIGINT);
442 break;
443
444 case CTRL_CLOSE_EVENT:
445 case CTRL_LOGOFF_EVENT:
446 case CTRL_SHUTDOWN_EVENT:
447 default:
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);
452 break;
453 }
454
455 // Return TRUE if the event was handled, or FALSE if another handler
456 // should be called.
457 // FIXME check that windows terminates the thread.
458 return TRUE;
459}
460#endif /* w32_sigint_handler */
461
462
463octave_interrupt_handler
464octave_catch_interrupts (void)
465{
466 octave_interrupt_handler retval;
467
468#ifdef SIGINT
469 retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
470#endif
471
472#ifdef SIGBREAK
473 retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
474#endif
475
476#ifdef USE_W32_SIGINT
477
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:
482 //
483 // SetConsoleCtrlHandler (w32_sigint_handler, FALSE);
484
485 if (! SetConsoleCtrlHandler (w32_sigint_handler, TRUE))
486 error ("SetConsoleCtrlHandler failed with %ld\n", GetLastError ());
487
488 w32_set_quiet_shutdown ();
489
490#endif
491
492 return retval;
493}
494
495octave_interrupt_handler
496octave_ignore_interrupts (void)
497{
498 octave_interrupt_handler retval;
499
500#ifdef SIGINT
501 retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
502#endif
503
504#ifdef SIGBREAK
505 retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
506#endif
507
508 return retval;
509}
510
511octave_interrupt_handler
512octave_set_interrupt_handler (const volatile octave_interrupt_handler& h,
513 bool restart_syscalls)
514{
515 octave_interrupt_handler retval;
516
517#ifdef SIGINT
518 retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
519 restart_syscalls);
520#endif
521
522#ifdef SIGBREAK
523 retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
524 restart_syscalls);
525#endif
526
527 return retval;
528}
529
530// Install all the handlers for the signals we might care about.
531
532void
533install_signal_handlers (void)
534{
535 for (int i = 0; i < NSIG; i++)
536 octave_signals_caught[i] = false;
537
538 octave_catch_interrupts ();
539
540#ifdef SIGABRT
541 octave_set_signal_handler (SIGABRT, generic_sig_handler);
542#endif
543
544#ifdef SIGALRM
545 octave_set_signal_handler (SIGALRM, generic_sig_handler);
546#endif
547
548#ifdef SIGBUS
549 octave_set_signal_handler (SIGBUS, generic_sig_handler);
550#endif
551
552#ifdef SIGCHLD
553 octave_set_signal_handler (SIGCHLD, sigchld_handler);
554#endif
555
556 // SIGCLD
557 // SIGCONT
558
559#ifdef SIGEMT
560 octave_set_signal_handler (SIGEMT, generic_sig_handler);
561#endif
562
563#ifdef SIGFPE
564#if defined (__alpha__)
565 octave_set_signal_handler (SIGFPE, sigfpe_handler);
566#else
567 octave_set_signal_handler (SIGFPE, generic_sig_handler);
568#endif
569#endif
570
571#ifdef SIGHUP
572 octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
573#endif
574
575#ifdef SIGILL
576 octave_set_signal_handler (SIGILL, generic_sig_handler);
577#endif
578
579 // SIGINFO
580 // SIGINT
581
582#ifdef SIGIOT
583 octave_set_signal_handler (SIGIOT, generic_sig_handler);
584#endif
585
586#ifdef SIGLOST
587 octave_set_signal_handler (SIGLOST, generic_sig_handler);
588#endif
589
590#ifdef SIGPIPE
591 octave_set_signal_handler (SIGPIPE, sigpipe_handler);
592#endif
593
594#ifdef SIGPOLL
595 octave_set_signal_handler (SIGPOLL, SIG_IGN);
596#endif
597
598 // SIGPROF
599 // SIGPWR
600
601#ifdef SIGQUIT
602 octave_set_signal_handler (SIGQUIT, generic_sig_handler);
603#endif
604
605#ifdef SIGSEGV
606 octave_set_signal_handler (SIGSEGV, generic_sig_handler);
607#endif
608
609 // SIGSTOP
610
611#ifdef SIGSYS
612 octave_set_signal_handler (SIGSYS, generic_sig_handler);
613#endif
614
615#ifdef SIGTERM
616 octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
617#endif
618
619#ifdef SIGTRAP
620 octave_set_signal_handler (SIGTRAP, generic_sig_handler);
621#endif
622
623 // SIGTSTP
624 // SIGTTIN
625 // SIGTTOU
626 // SIGURG
627
628#ifdef SIGUSR1
629 octave_set_signal_handler (SIGUSR1, generic_sig_handler);
630#endif
631
632#ifdef SIGUSR2
633 octave_set_signal_handler (SIGUSR2, generic_sig_handler);
634#endif
635
636#ifdef SIGVTALRM
637 octave_set_signal_handler (SIGVTALRM, generic_sig_handler);
638#endif
639
640#ifdef SIGIO
641 octave_set_signal_handler (SIGIO, SIG_IGN);
642#endif
643
644#if 0
645#ifdef SIGWINCH
646 octave_set_signal_handler (SIGWINCH, sigwinch_handler);
647#endif
648#endif
649
650#ifdef SIGXCPU
651 octave_set_signal_handler (SIGXCPU, generic_sig_handler);
652#endif
653
654#ifdef SIGXFSZ
655 octave_set_signal_handler (SIGXFSZ, generic_sig_handler);
656#endif
657
658}
659
660static Octave_map
661make_sig_struct (void)
662{
663 Octave_map m;
664
665#ifdef SIGABRT
666 m.assign ("ABRT", SIGABRT);
667#endif
668
669#ifdef SIGALRM
670 m.assign ("ALRM", SIGALRM);
671#endif
672
673#ifdef SIGBUS
674 m.assign ("BUS", SIGBUS);
675#endif
676
677#ifdef SIGCHLD
678 m.assign ("CHLD", SIGCHLD);
679#endif
680
681#ifdef SIGCLD
682 m.assign ("CLD", SIGCLD);
683#endif
684
685#ifdef SIGCONT
686 m.assign ("CONT", SIGCONT);
687#endif
688
689#ifdef SIGEMT
690 m.assign ("EMT", SIGEMT);
691#endif
692
693#ifdef SIGFPE
694 m.assign ("FPE", SIGFPE);
695#endif
696
697#ifdef SIGHUP
698 m.assign ("HUP", SIGHUP);
699#endif
700
701#ifdef SIGILL
702 m.assign ("ILL", SIGILL);
703#endif
704
705#ifdef SIGINFO
706 m.assign ("INFO", SIGINFO);
707#endif
708
709#ifdef SIGINT
710 m.assign ("INT", SIGINT);
711#endif
712
713#ifdef SIGIOT
714 m.assign ("IOT", SIGIOT);
715#endif
716
717#ifdef SIGLOST
718 m.assign ("LOST", SIGLOST);
719#endif
720
721#ifdef SIGPIPE
722 m.assign ("PIPE", SIGPIPE);
723#endif
724
725#ifdef SIGPOLL
726 m.assign ("POLL", SIGPOLL);
727#endif
728
729#ifdef SIGPROF
730 m.assign ("PROF", SIGPROF);
731#endif
732
733#ifdef SIGPWR
734 m.assign ("PWR", SIGPWR);
735#endif
736
737#ifdef SIGQUIT
738 m.assign ("QUIT", SIGQUIT);
739#endif
740
741#ifdef SIGSEGV
742 m.assign ("SEGV", SIGSEGV);
743#endif
744
745#ifdef SIGSTOP
746 m.assign ("STOP", SIGSTOP);
747#endif
748
749#ifdef SIGSYS
750 m.assign ("SYS", SIGSYS);
751#endif
752
753#ifdef SIGTERM
754 m.assign ("TERM", SIGTERM);
755#endif
756
757#ifdef SIGTRAP
758 m.assign ("TRAP", SIGTRAP);
759#endif
760
761#ifdef SIGTSTP
762 m.assign ("TSTP", SIGTSTP);
763#endif
764
765#ifdef SIGTTIN
766 m.assign ("TTIN", SIGTTIN);
767#endif
768
769#ifdef SIGTTOU
770 m.assign ("TTOU", SIGTTOU);
771#endif
772
773#ifdef SIGURG
774 m.assign ("URG", SIGURG);
775#endif
776
777#ifdef SIGUSR1
778 m.assign ("USR1", SIGUSR1);
779#endif
780
781#ifdef SIGUSR2
782 m.assign ("USR2", SIGUSR2);
783#endif
784
785#ifdef SIGVTALRM
786 m.assign ("VTALRM", SIGVTALRM);
787#endif
788
789#ifdef SIGIO
790 m.assign ("IO", SIGIO);
791#endif
792
793#ifdef SIGWINCH
794 m.assign ("WINCH", SIGWINCH);
795#endif
796
797#ifdef SIGXCPU
798 m.assign ("XCPU", SIGXCPU);
799#endif
800
801#ifdef SIGXFSZ
802 m.assign ("XFSZ", SIGXFSZ);
803#endif
804
805 return m;
806}
807
808octave_child_list::octave_child_list_rep *octave_child_list::instance = 0;
809
810bool
811octave_child_list::instance_ok (void)
812{
813 bool retval = true;
814
815 if (! instance)
816 instance = new octave_child_list_rep ();
817
818 if (! instance)
819 {
820 ::error ("unable to create child list object!");
821
822 retval = false;
823 }
824
825 return retval;
826}
827
828void
829octave_child_list::insert (pid_t pid, octave_child::child_event_handler f)
830{
831 if (instance_ok ())
832 instance->insert (pid, f);
833}
834
835void
836octave_child_list::reap (void)
837{
838 if (instance_ok ())
839 instance->reap ();
840}
841
842bool
843octave_child_list::wait (void)
844{
845 return (instance_ok ()) ? instance->wait () : false;
846}
847
848class pid_equal
849{
850public:
851
852 pid_equal (pid_t v) : val (v) { }
853
854 bool operator () (const octave_child& oc) const { return oc.pid == val; }
855
856private:
857
858 pid_t val;
859};
860
861void
862octave_child_list::remove (pid_t pid)
863{
864 if (instance_ok ())
865 instance->remove_if (pid_equal (pid));
866}
867
868#define OCL_REP octave_child_list::octave_child_list_rep
869
870void
871OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
872{
873 append (octave_child (pid, f));
874}
875
876void
877OCL_REP::reap (void)
878{
879 // Mark the record for PID invalid.
880
881 for (iterator p = begin (); p != end (); p++)
882 {
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
886 // here.
887
888 octave_child& oc = *p;
889
890 if (oc.have_status)
891 {
892 oc.have_status = 0;
893
894 octave_child::child_event_handler f = oc.handler;
895
896 if (f && f (oc.pid, oc.status))
897 oc.pid = -1;
898 }
899 }
900
901 remove_if (pid_equal (-1));
902}
903
904// Wait on our children and record any changes in their status.
905
906bool
907OCL_REP::wait (void)
908{
909 bool retval = false;
910
911 for (iterator p = begin (); p != end (); p++)
912 {
913 octave_child& oc = *p;
914
915 pid_t pid = oc.pid;
916
917 if (pid > 0)
918 {
919 int status;
920
921 if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
922 {
923 oc.have_status = 1;
924
925 oc.status = status;
926
927 retval = true;
928
929 break;
930 }
931 }
932 }
933
934 return retval;
935}
936
937DEFUN (SIG, args, ,
938 "-*- texinfo -*-\n\
939@deftypefn {Built-in Function} {} SIG ()\n\
940Return a structure containing Unix signal names and their defined values.\n\
941@end deftypefn")
942{
943 octave_value retval;
944
945 if (args.length () == 0)
946 {
947 static Octave_map m = make_sig_struct ();
948
949 retval = m;
950 }
951 else
952 print_usage ();
953
954 return retval;
955}
956
957DEFUN (debug_on_interrupt, args, nargout,
958 "-*- texinfo -*-\n\
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\
965@end deftypefn")
966{
967 return SET_INTERNAL_VARIABLE (debug_on_interrupt);
968}
969
970DEFUN (sighup_dumps_octave_core, args, nargout,
971 "-*- texinfo -*-\n\
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\
976a hangup signal.\n\
977@end deftypefn")
978{
979 return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
980}
981
982DEFUN (sigterm_dumps_octave_core, args, nargout,
983 "-*- texinfo -*-\n\
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\
989@end deftypefn")
990{
991 return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
992}