GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
sighandlers.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <cstdlib>
28 
29 #include <iostream>
30 #include <new>
31 
32 #include <sys/types.h>
33 #include <unistd.h>
34 
35 #include "cmd-edit.h"
36 #include "oct-syscalls.h"
37 #include "quit.h"
38 #include "singleton-cleanup.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.
59 
60 // TRUE means we can be interrupted.
61 bool can_interrupt = false;
62 
63 // TRUE means we should try to enter the debugger on SIGINT.
64 bool Vdebug_on_interrupt = false;
65 
66 // Allow users to avoid writing octave-workspace 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.
69 static bool Vsighup_dumps_octave_core = true;
70 
71 // Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
72 static bool Vsigterm_dumps_octave_core = true;
73 
74 // List of signals we have caught since last call to octave_signal_handler.
75 static bool octave_signals_caught[NSIG];
76 
77 // Forward declaration.
78 static void user_abort (const char *sig_name, int sig_number);
79 
80 #if defined (__WIN32__) && ! defined (__CYGWIN__)
81 
82 #define WIN32_LEAN_AND_MEAN
83 #include <windows.h>
84 
85 class
86 w32_interrupt_manager
87 {
88 public:
89  ~w32_interrupt_manager (void)
90  {
91  if (thread)
92  CloseHandle (thread);
93  }
94 
95  static bool init (void) { return instance_ok (); }
96 
97  static void octave_jump_to_enclosing_context (void)
98  {
99  if (instance_ok ())
100  instance->do_octave_jump_to_enclosing_context ();
101  }
102 
103  static void user_abort (const char *sig_name, int sig_number)
104  {
105  if (instance_ok ())
106  instance->do_user_abort (sig_name, sig_number);
107  }
108 
109  static void raise_sigint (void)
110  {
111  if (instance_ok ())
112  instance->do_raise_sigint ();
113  }
114 
115 private:
116  w32_interrupt_manager (void)
117  : thread (0), thread_id (0)
118  {
119  thread_id = GetCurrentThreadId ();
120 
121  DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
122  GetCurrentProcess (), &thread, 0, FALSE,
123  DUPLICATE_SAME_ACCESS);
124  }
125 
126  static void octave_jump_to_enclosing_context_sync (void)
127  {
128 #ifdef _MSC_VER
129  _fpreset ();
130 #endif
132  }
133 
134  void do_octave_jump_to_enclosing_context (void)
135  {
136  bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
137 
138  if (is_interrupt_thread)
139  octave_jump_to_enclosing_context_sync ();
140  else
141  {
142  CONTEXT threadContext;
143 
144  SuspendThread (thread);
145  threadContext.ContextFlags = CONTEXT_CONTROL;
146  GetThreadContext (thread, &threadContext);
147  threadContext.Eip = (DWORD) octave_jump_to_enclosing_context_sync;
148  SetThreadContext (thread, &threadContext);
149  ResumeThread (thread);
150  }
151  }
152 
153  void do_user_abort (const char *sig_name, int sig_number)
154  {
155  bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
156 
157  if (is_interrupt_thread)
158  ::user_abort (sig_name, sig_number);
159  else
160  {
161  SuspendThread (thread);
162  ::user_abort (sig_name, sig_number);
163  ResumeThread (thread);
164  }
165  }
166 
167  void do_raise_sigint (void)
168  {
169  bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
170 
171  if (is_interrupt_thread)
172  ::raise (SIGINT);
173  else
174  {
175  SuspendThread (thread);
176  ::raise (SIGINT);
177  ResumeThread (thread);
178  }
179  }
180 
181  static bool instance_ok (void)
182  {
183  bool retval = true;
184 
185  if (! instance)
186  {
187  instance = new w32_interrupt_manager ();
188 
189  if (instance)
190  singleton_cleanup_list::add (cleanup_instance);
191  }
192 
193  if (! instance)
194  {
195  ::error ("unable to create w32_interrupt_manager");
196 
197  retval = false;
198  }
199 
200  return retval;
201  }
202 
203  static void cleanup_instance (void) { delete instance; instance = 0; }
204 
205 private:
206  // A handle to the thread that is running the octave interpreter.
207  HANDLE thread;
208 
209  // The ID of the thread that is running the octave interpreter.
210  DWORD thread_id;
211 
212  static w32_interrupt_manager* instance;
213 };
214 
215 w32_interrupt_manager* w32_interrupt_manager::instance = 0;
216 
217 void w32_raise_sigint (void)
218 {
219  w32_interrupt_manager::raise_sigint ();
220 }
221 
222 #endif
223 
224 // Signal handler return type.
225 #ifndef BADSIG
226 #define BADSIG (void (*)(int))-1
227 #endif
228 
229 // The following is a workaround for an apparent bug in GCC 4.1.2 and
230 // possibly earlier versions. See Octave bug report #30685 for details.
231 #if defined (__GNUC__)
232 # if ! (__GNUC__ > 4 \
233  || (__GNUC__ == 4 && (__GNUC_MINOR__ > 1 \
234  || (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ > 2))))
235 # undef GNULIB_NAMESPACE
236 # define GNULIB_NAMESPACE
237 # warning "disabling GNULIB_NAMESPACE for signal functions -- consider upgrading to a current version of GCC"
238 # endif
239 #endif
240 
241 #define BLOCK_SIGNAL(sig, nvar, ovar) \
242  do \
243  { \
244  GNULIB_NAMESPACE::sigemptyset (&nvar); \
245  GNULIB_NAMESPACE::sigaddset (&nvar, sig); \
246  GNULIB_NAMESPACE::sigemptyset (&ovar); \
247  GNULIB_NAMESPACE::sigprocmask (SIG_BLOCK, &nvar, &ovar); \
248  } \
249  while (0)
250 
251 #if !defined (SIGCHLD) && defined (SIGCLD)
252 #define SIGCHLD SIGCLD
253 #endif
254 
255 #define BLOCK_CHILD(nvar, ovar) BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
256 #define UNBLOCK_CHILD(ovar) GNULIB_NAMESPACE::sigprocmask (SIG_SETMASK, &ovar, 0)
257 
258 // Called from octave_quit () to actually do something about the signals
259 // we have caught.
260 
261 void
263 {
264  // The list of signals is relatively short, so we will just go
265  // linearly through the list.
266 
267  for (int i = 0; i < NSIG; i++)
268  {
269  if (octave_signals_caught[i])
270  {
271  octave_signals_caught[i] = false;
272 
273  switch (i)
274  {
275 #ifdef SIGCHLD
276  case SIGCHLD:
277  {
278  volatile octave_interrupt_handler saved_interrupt_handler
280 
281  sigset_t set, oset;
282 
283  BLOCK_CHILD (set, oset);
284 
286 
287  octave_set_interrupt_handler (saved_interrupt_handler);
288 
289  UNBLOCK_CHILD (oset);
290 
292  }
293  break;
294 #endif
295 
296  case SIGFPE:
297  std::cerr << "warning: floating point exception" << std::endl;
298  break;
299 
300 #ifdef SIGPIPE
301  case SIGPIPE:
302  std::cerr << "warning: broken pipe" << std::endl;
303  break;
304 #endif
305  }
306  }
307  }
308 }
309 
310 static void
311 my_friendly_exit (const char *sig_name, int sig_number,
312  bool save_vars = true)
313 {
314  static bool been_there_done_that = false;
315 
316  if (been_there_done_that)
317  {
318 #if defined (SIGABRT)
319  octave_set_signal_handler (SIGABRT, SIG_DFL);
320 #endif
321 
322  std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";
323 
325 
326  abort ();
327  }
328  else
329  {
330  been_there_done_that = true;
331 
332  std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
333 
334  if (save_vars)
335  dump_octave_core ();
336 
337  if (sig_number < 0)
338  {
340 
341  exit (1);
342  }
343  else
344  {
345  octave_set_signal_handler (sig_number, SIG_DFL);
346 
347  GNULIB_NAMESPACE::raise (sig_number);
348  }
349  }
350 }
351 
352 sig_handler *
354  bool restart_syscalls)
355 {
356  struct sigaction act, oact;
357 
358  act.sa_handler = handler;
359  act.sa_flags = 0;
360 
361 #if defined (SIGALRM)
362  if (sig == SIGALRM)
363  {
364 #if defined (SA_INTERRUPT)
365  act.sa_flags |= SA_INTERRUPT;
366 #endif
367  }
368 #endif
369 #if defined (SA_RESTART)
370 #if defined (SIGALRM)
371  else
372 #endif
373  // FIXME: Do we also need to explicitly disable SA_RESTART?
374  if (restart_syscalls)
375  act.sa_flags |= SA_RESTART;
376 #endif
377 
378  GNULIB_NAMESPACE::sigemptyset (&act.sa_mask);
379  GNULIB_NAMESPACE::sigemptyset (&oact.sa_mask);
380 
381  GNULIB_NAMESPACE::sigaction (sig, &act, &oact);
382 
383  return oact.sa_handler;
384 }
385 
386 static void
388 {
389  my_friendly_exit (strsignal (sig), sig);
390 }
391 
392 // Handle SIGCHLD.
393 
394 #ifdef SIGCHLD
395 static void
396 sigchld_handler (int /* sig */)
397 {
399 
400  octave_signals_caught[SIGCHLD] = true;
401 }
402 #endif /* defined (SIGCHLD) */
403 
404 #ifdef SIGFPE
405 #if defined (__alpha__)
406 static void
407 sigfpe_handler (int /* sig */)
408 {
410  {
412 
413  octave_signals_caught[SIGFPE] = true;
414 
416  }
417 }
418 #endif /* defined (__alpha__) */
419 #endif /* defined (SIGFPE) */
420 
421 #if defined (SIGHUP) || defined (SIGTERM)
422 static void
423 sig_hup_or_term_handler (int sig)
424 {
425  switch (sig)
426  {
427 #if defined (SIGHUP)
428  case SIGHUP:
429  {
431  dump_octave_core ();
432  }
433  break;
434 #endif
435 
436 #if defined (SIGTERM)
437  case SIGTERM:
438  {
440  dump_octave_core ();
441  }
442  break;
443 #endif
444 
445  default:
446  break;
447  }
448 
449  clean_up_and_exit (0);
450 }
451 #endif
452 
453 #if 0
454 #if defined (SIGWINCH)
455 static void
456 sigwinch_handler (int /* sig */)
457 {
459 }
460 #endif
461 #endif
462 
463 // Handle SIGINT by restarting the parser (see octave.cc).
464 //
465 // This also has to work for SIGBREAK (on systems that have it), so we
466 // use the value of sig, instead of just assuming that it is called
467 // for SIGINT only.
468 
469 static void
470 user_abort (const char *sig_name, int sig_number)
471 {
472  if (! octave_initialized)
473  exit (1);
474 
475  if (can_interrupt)
476  {
478  {
480  {
483 
484  return;
485  }
486  else
487  {
488  // Clear the flag and do normal interrupt stuff.
489 
493  }
494  }
495 
497  {
498  if (octave_interrupt_state == 0)
500 
501 #if defined (__WIN32__) && ! defined (__CYGWIN__)
503 #else
505 #endif
506  }
507  else
508  {
509  // If we are already cleaning up from a previous interrupt,
510  // take note of the fact that another interrupt signal has
511  // arrived.
512 
513  if (octave_interrupt_state < 0)
515 
518 
520  std::cerr << "Press Control-C again to abort." << std::endl;
521 
522  if (octave_interrupt_state >= 3)
523  my_friendly_exit (sig_name, sig_number, true);
524  }
525  }
526 
527 }
528 
529 static void
530 sigint_handler (int sig)
531 {
532 #if defined (__WIN32__) && ! defined (__CYGWIN__)
534 #else
535  user_abort (strsignal (sig), sig);
536 #endif
537 }
538 
539 #ifdef SIGPIPE
540 static void
541 sigpipe_handler (int /* sig */)
542 {
544 
545  octave_signals_caught[SIGPIPE] = true;
546 
547  // Don't loop forever on account of this.
548 
549  if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
551 }
552 #endif /* defined (SIGPIPE) */
553 
556 {
558 
559 #if defined (__WIN32__) && ! defined (__CYGWIN__)
560  w32_interrupt_manager::init ();
561 #endif
562 
563 #ifdef SIGINT
564  retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
565 #endif
566 
567 #ifdef SIGBREAK
568  retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
569 #endif
570 
571  return retval;
572 }
573 
576 {
578 
579 #if defined (__WIN32__) && ! defined (__CYGWIN__)
580  w32_interrupt_manager::init ();
581 #endif
582 
583 #ifdef SIGINT
584  retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
585 #endif
586 
587 #ifdef SIGBREAK
588  retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
589 #endif
590 
591  return retval;
592 }
593 
596  bool restart_syscalls)
597 {
599 
600 #if defined (__WIN32__) && ! defined (__CYGWIN__)
601  w32_interrupt_manager::init ();
602 #endif
603 
604 #ifdef SIGINT
605  retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
606  restart_syscalls);
607 #endif
608 
609 #ifdef SIGBREAK
610  retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
611  restart_syscalls);
612 #endif
613 
614  return retval;
615 }
616 
617 // Install all the handlers for the signals we might care about.
618 
619 void
621 {
622  for (int i = 0; i < NSIG; i++)
623  octave_signals_caught[i] = false;
624 
626 
627 #ifdef SIGABRT
629 #endif
630 
631 #ifdef SIGALRM
633 #endif
634 
635 #ifdef SIGBUS
637 #endif
638 
639 #ifdef SIGCHLD
640  octave_set_signal_handler (SIGCHLD, sigchld_handler);
641 #endif
642 
643  // SIGCLD
644  // SIGCONT
645 
646 #ifdef SIGEMT
648 #endif
649 
650 #ifdef SIGFPE
651 #if defined (__alpha__)
652  octave_set_signal_handler (SIGFPE, sigfpe_handler);
653 #else
655 #endif
656 #endif
657 
658 #ifdef SIGHUP
659  octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
660 #endif
661 
662 #ifdef SIGILL
664 #endif
665 
666  // SIGINFO
667  // SIGINT
668 
669 #ifdef SIGIOT
671 #endif
672 
673 #ifdef SIGLOST
675 #endif
676 
677 #ifdef SIGPIPE
678  octave_set_signal_handler (SIGPIPE, sigpipe_handler);
679 #endif
680 
681 #ifdef SIGPOLL
682  octave_set_signal_handler (SIGPOLL, SIG_IGN);
683 #endif
684 
685  // SIGPROF
686  // SIGPWR
687 
688 #ifdef SIGQUIT
690 #endif
691 
692 #ifdef SIGSEGV
694 #endif
695 
696  // SIGSTOP
697 
698 #ifdef SIGSYS
700 #endif
701 
702 #ifdef SIGTERM
703  octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
704 #endif
705 
706 #ifdef SIGTRAP
708 #endif
709 
710  // SIGTSTP
711  // SIGTTIN
712  // SIGTTOU
713  // SIGURG
714 
715 #ifdef SIGUSR1
717 #endif
718 
719 #ifdef SIGUSR2
721 #endif
722 
723 #ifdef SIGVTALRM
725 #endif
726 
727 #ifdef SIGIO
728  octave_set_signal_handler (SIGIO, SIG_IGN);
729 #endif
730 
731 #if 0
732 #ifdef SIGWINCH
733  octave_set_signal_handler (SIGWINCH, sigwinch_handler);
734 #endif
735 #endif
736 
737 #ifdef SIGXCPU
739 #endif
740 
741 #ifdef SIGXFSZ
743 #endif
744 
745 }
746 
747 static octave_scalar_map
749 {
751 
752 #ifdef SIGABRT
753  m.assign ("ABRT", SIGABRT);
754 #endif
755 
756 #ifdef SIGALRM
757  m.assign ("ALRM", SIGALRM);
758 #endif
759 
760 #ifdef SIGBUS
761  m.assign ("BUS", SIGBUS);
762 #endif
763 
764 #ifdef SIGCHLD
765  m.assign ("CHLD", SIGCHLD);
766 #endif
767 
768 #ifdef SIGCLD
769  m.assign ("CLD", SIGCLD);
770 #endif
771 
772 #ifdef SIGCONT
773  m.assign ("CONT", SIGCONT);
774 #endif
775 
776 #ifdef SIGEMT
777  m.assign ("EMT", SIGEMT);
778 #endif
779 
780 #ifdef SIGFPE
781  m.assign ("FPE", SIGFPE);
782 #endif
783 
784 #ifdef SIGHUP
785  m.assign ("HUP", SIGHUP);
786 #endif
787 
788 #ifdef SIGILL
789  m.assign ("ILL", SIGILL);
790 #endif
791 
792 #ifdef SIGINFO
793  m.assign ("INFO", SIGINFO);
794 #endif
795 
796 #ifdef SIGINT
797  m.assign ("INT", SIGINT);
798 #endif
799 
800 #ifdef SIGIO
801  m.assign ("IO", SIGIO);
802 #endif
803 
804 #ifdef SIGIOT
805  m.assign ("IOT", SIGIOT);
806 #endif
807 
808 #ifdef SIGKILL
809  m.assign ("KILL", SIGKILL);
810 #endif
811 
812 #ifdef SIGLOST
813  m.assign ("LOST", SIGLOST);
814 #endif
815 
816 #ifdef SIGPIPE
817  m.assign ("PIPE", SIGPIPE);
818 #endif
819 
820 #ifdef SIGPOLL
821  m.assign ("POLL", SIGPOLL);
822 #endif
823 
824 #ifdef SIGPROF
825  m.assign ("PROF", SIGPROF);
826 #endif
827 
828 #ifdef SIGPWR
829  m.assign ("PWR", SIGPWR);
830 #endif
831 
832 #ifdef SIGQUIT
833  m.assign ("QUIT", SIGQUIT);
834 #endif
835 
836 #ifdef SIGSEGV
837  m.assign ("SEGV", SIGSEGV);
838 #endif
839 
840 #ifdef SIGSTKFLT
841  m.assign ("STKFLT", SIGSTKFLT);
842 #endif
843 
844 #ifdef SIGSTOP
845  m.assign ("STOP", SIGSTOP);
846 #endif
847 
848 #ifdef SIGSYS
849  m.assign ("SYS", SIGSYS);
850 #endif
851 
852 #ifdef SIGTERM
853  m.assign ("TERM", SIGTERM);
854 #endif
855 
856 #ifdef SIGTRAP
857  m.assign ("TRAP", SIGTRAP);
858 #endif
859 
860 #ifdef SIGTSTP
861  m.assign ("TSTP", SIGTSTP);
862 #endif
863 
864 #ifdef SIGTTIN
865  m.assign ("TTIN", SIGTTIN);
866 #endif
867 
868 #ifdef SIGTTOU
869  m.assign ("TTOU", SIGTTOU);
870 #endif
871 
872 #ifdef SIGUNUSED
873  m.assign ("UNUSED", SIGUNUSED);
874 #endif
875 
876 #ifdef SIGURG
877  m.assign ("URG", SIGURG);
878 #endif
879 
880 #ifdef SIGUSR1
881  m.assign ("USR1", SIGUSR1);
882 #endif
883 
884 #ifdef SIGUSR2
885  m.assign ("USR2", SIGUSR2);
886 #endif
887 
888 #ifdef SIGVTALRM
889  m.assign ("VTALRM", SIGVTALRM);
890 #endif
891 
892 #ifdef SIGWINCH
893  m.assign ("WINCH", SIGWINCH);
894 #endif
895 
896 #ifdef SIGXCPU
897  m.assign ("XCPU", SIGXCPU);
898 #endif
899 
900 #ifdef SIGXFSZ
901  m.assign ("XFSZ", SIGXFSZ);
902 #endif
903 
904  return m;
905 }
906 
908 
909 bool
911 {
912  bool retval = true;
913 
914  if (! instance)
915  {
917 
918  if (instance)
920  }
921 
922  if (! instance)
923  {
924  ::error ("unable to create child list object!");
925 
926  retval = false;
927  }
928 
929  return retval;
930 }
931 
932 void
934 {
935  if (instance_ok ())
936  instance->insert (pid, f);
937 }
938 
939 void
941 {
942  if (instance_ok ())
943  instance->reap ();
944 }
945 
946 bool
948 {
949  return (instance_ok ()) ? instance->wait () : false;
950 }
951 
953 {
954 public:
955 
956  pid_equal (pid_t v) : val (v) { }
957 
958  bool operator () (const octave_child& oc) const { return oc.pid == val; }
959 
960 private:
961 
962  pid_t val;
963 };
964 
965 void
967 {
968  if (instance_ok ())
969  instance->remove_if (pid_equal (pid));
970 }
971 
972 #define OCL_REP octave_child_list::octave_child_list_rep
973 
974 void
975 OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
976 {
977  append (octave_child (pid, f));
978 }
979 
980 void
981 OCL_REP::reap (void)
982 {
983  // Mark the record for PID invalid.
984 
985  for (iterator p = begin (); p != end (); p++)
986  {
987  // The call to the octave_child::child_event_handler might
988  // invalidate the iterator (for example, by calling
989  // octave_child_list::remove), so we increment the iterator
990  // here.
991 
992  octave_child& oc = *p;
993 
994  if (oc.have_status)
995  {
996  oc.have_status = 0;
997 
999 
1000  if (f && f (oc.pid, oc.status))
1001  oc.pid = -1;
1002  }
1003  }
1004 
1005  remove_if (pid_equal (-1));
1006 }
1007 
1008 // Wait on our children and record any changes in their status.
1009 
1010 bool
1011 OCL_REP::wait (void)
1012 {
1013  bool retval = false;
1014 
1015  for (iterator p = begin (); p != end (); p++)
1016  {
1017  octave_child& oc = *p;
1018 
1019  pid_t pid = oc.pid;
1020 
1021  if (pid > 0)
1022  {
1023  int status;
1024 
1025  if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
1026  {
1027  oc.have_status = 1;
1028 
1029  oc.status = status;
1030 
1031  retval = true;
1032 
1033  break;
1034  }
1035  }
1036  }
1037 
1038  return retval;
1039 }
1040 
1041 DEFUN (SIG, args, ,
1042  "-*- texinfo -*-\n\
1043 @deftypefn {Built-in Function} {} SIG ()\n\
1044 Return a structure containing Unix signal names and their defined values.\n\
1045 @end deftypefn")
1046 {
1047  octave_value retval;
1048 
1049  if (args.length () == 0)
1050  {
1051  static octave_scalar_map m = make_sig_struct ();
1052 
1053  retval = m;
1054  }
1055  else
1056  print_usage ();
1057 
1058  return retval;
1059 }
1060 
1061 /*
1062 %!assert (isstruct (SIG ()))
1063 %!assert (! isempty (SIG ()))
1064 
1065 %!error SIG (1)
1066 */
1067 
1068 DEFUN (debug_on_interrupt, args, nargout,
1069  "-*- texinfo -*-\n\
1070 @deftypefn {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
1071 @deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\
1072 @deftypefnx {Built-in Function} {} debug_on_interrupt (@var{new_val}, \"local\")\n\
1073 Query or set the internal variable that controls whether Octave will try\n\
1074 to enter debugging mode when it receives an interrupt signal (typically\n\
1075 generated with @kbd{C-c}). If a second interrupt signal is received\n\
1076 before reaching the debugging mode, a normal interrupt will occur.\n\
1077 \n\
1078 When called from inside a function with the @qcode{\"local\"} option, the\n\
1079 variable is changed locally for the function and any subroutines it calls. \n\
1080 The original variable value is restored when exiting the function.\n\
1081 @seealso{debug_on_error, debug_on_warning}\n\
1082 @end deftypefn")
1083 {
1084  return SET_INTERNAL_VARIABLE (debug_on_interrupt);
1085 }
1086 
1087 /*
1088 %!test
1089 %! orig_val = debug_on_interrupt ();
1090 %! old_val = debug_on_interrupt (! orig_val);
1091 %! assert (orig_val, old_val);
1092 %! assert (debug_on_interrupt (), ! orig_val);
1093 %! debug_on_interrupt (orig_val);
1094 %! assert (debug_on_interrupt (), orig_val);
1095 
1096 %!error (debug_on_interrupt (1, 2))
1097 */
1098 
1099 DEFUN (sighup_dumps_octave_core, args, nargout,
1100  "-*- texinfo -*-\n\
1101 @deftypefn {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
1102 @deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\
1103 @deftypefnx {Built-in Function} {} sighup_dumps_octave_core (@var{new_val}, \"local\")\n\
1104 Query or set the internal variable that controls whether Octave tries\n\
1105 to save all current variables to the file @file{octave-workspace} if it\n\
1106 receives a hangup signal.\n\
1107 \n\
1108 When called from inside a function with the @qcode{\"local\"} option, the\n\
1109 variable is changed locally for the function and any subroutines it calls. \n\
1110 The original variable value is restored when exiting the function.\n\
1111 @end deftypefn")
1112 {
1113  return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
1114 }
1115 
1116 /*
1117 %!test
1118 %! orig_val = sighup_dumps_octave_core ();
1119 %! old_val = sighup_dumps_octave_core (! orig_val);
1120 %! assert (orig_val, old_val);
1121 %! assert (sighup_dumps_octave_core (), ! orig_val);
1122 %! sighup_dumps_octave_core (orig_val);
1123 %! assert (sighup_dumps_octave_core (), orig_val);
1124 
1125 %!error (sighup_dumps_octave_core (1, 2))
1126 */
1127 
1128 DEFUN (sigterm_dumps_octave_core, args, nargout,
1129  "-*- texinfo -*-\n\
1130 @deftypefn {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
1131 @deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\
1132 @deftypefnx {Built-in Function} {} sigterm_dumps_octave_core (@var{new_val}, \"local\")\n\
1133 Query or set the internal variable that controls whether Octave tries\n\
1134 to save all current variables to the file @file{octave-workspace} if it\n\
1135 receives a terminate signal.\n\
1136 \n\
1137 When called from inside a function with the @qcode{\"local\"} option, the\n\
1138 variable is changed locally for the function and any subroutines it calls. \n\
1139 The original variable value is restored when exiting the function.\n\
1140 @end deftypefn")
1141 {
1142  return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
1143 }
1144 
1145 /*
1146 %!test
1147 %! orig_val = sigterm_dumps_octave_core ();
1148 %! old_val = sigterm_dumps_octave_core (! orig_val);
1149 %! assert (orig_val, old_val);
1150 %! assert (sigterm_dumps_octave_core (), ! orig_val);
1151 %! sigterm_dumps_octave_core (orig_val);
1152 %! assert (sigterm_dumps_octave_core (), orig_val);
1153 
1154 %!error (sigterm_dumps_octave_core (1, 2))
1155 */