GNU Octave  4.0.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-2015 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  // 64-bit Windows does not appear to have threadContext.Eip.
143  // Something else must be done here to allow interrupts to
144  // properly work across threads.
145 
146 #if ! (defined (__MINGW64__) || defined (_WIN64))
147 
148  CONTEXT threadContext;
149 
150  SuspendThread (thread);
151  threadContext.ContextFlags = CONTEXT_CONTROL;
152  GetThreadContext (thread, &threadContext);
153  threadContext.Eip = (DWORD) octave_jump_to_enclosing_context_sync;
154  SetThreadContext (thread, &threadContext);
155  ResumeThread (thread);
156 #endif
157  }
158  }
159 
160  void do_user_abort (const char *sig_name, int sig_number)
161  {
162  bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
163 
164  if (is_interrupt_thread)
165  ::user_abort (sig_name, sig_number);
166  else
167  {
168  SuspendThread (thread);
169  ::user_abort (sig_name, sig_number);
170  ResumeThread (thread);
171  }
172  }
173 
174  void do_raise_sigint (void)
175  {
176  bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
177 
178  if (is_interrupt_thread)
179  ::raise (SIGINT);
180  else
181  {
182  SuspendThread (thread);
183  ::raise (SIGINT);
184  ResumeThread (thread);
185  }
186  }
187 
188  static bool instance_ok (void)
189  {
190  bool retval = true;
191 
192  if (! instance)
193  {
194  instance = new w32_interrupt_manager ();
195 
196  if (instance)
197  singleton_cleanup_list::add (cleanup_instance);
198  }
199 
200  if (! instance)
201  {
202  ::error ("unable to create w32_interrupt_manager");
203 
204  retval = false;
205  }
206 
207  return retval;
208  }
209 
210  static void cleanup_instance (void) { delete instance; instance = 0; }
211 
212 private:
213  // A handle to the thread that is running the octave interpreter.
214  HANDLE thread;
215 
216  // The ID of the thread that is running the octave interpreter.
217  DWORD thread_id;
218 
219  static w32_interrupt_manager* instance;
220 };
221 
222 w32_interrupt_manager* w32_interrupt_manager::instance = 0;
223 
224 void w32_raise_sigint (void)
225 {
226  w32_interrupt_manager::raise_sigint ();
227 }
228 
229 #endif
230 
231 // Signal handler return type.
232 #ifndef BADSIG
233 #define BADSIG (void (*)(int))-1
234 #endif
235 
236 // The following is a workaround for an apparent bug in GCC 4.1.2 and
237 // possibly earlier versions. See Octave bug report #30685 for details.
238 #if defined (__GNUC__)
239 # if ! (__GNUC__ > 4 \
240  || (__GNUC__ == 4 && (__GNUC_MINOR__ > 1 \
241  || (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ > 2))))
242 # undef GNULIB_NAMESPACE
243 # define GNULIB_NAMESPACE
244 # warning "disabling GNULIB_NAMESPACE for signal functions -- consider upgrading to a current version of GCC"
245 # endif
246 #endif
247 
248 #define BLOCK_SIGNAL(sig, nvar, ovar) \
249  do \
250  { \
251  GNULIB_NAMESPACE::sigemptyset (&nvar); \
252  GNULIB_NAMESPACE::sigaddset (&nvar, sig); \
253  GNULIB_NAMESPACE::sigemptyset (&ovar); \
254  GNULIB_NAMESPACE::sigprocmask (SIG_BLOCK, &nvar, &ovar); \
255  } \
256  while (0)
257 
258 #if !defined (SIGCHLD) && defined (SIGCLD)
259 #define SIGCHLD SIGCLD
260 #endif
261 
262 #define BLOCK_CHILD(nvar, ovar) BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
263 #define UNBLOCK_CHILD(ovar) GNULIB_NAMESPACE::sigprocmask (SIG_SETMASK, &ovar, 0)
264 
265 // Called from octave_quit () to actually do something about the signals
266 // we have caught.
267 
268 void
270 {
271  // The list of signals is relatively short, so we will just go
272  // linearly through the list.
273 
274  for (int i = 0; i < NSIG; i++)
275  {
276  if (octave_signals_caught[i])
277  {
278  octave_signals_caught[i] = false;
279 
280  switch (i)
281  {
282 #ifdef SIGCHLD
283  case SIGCHLD:
284  {
285  volatile octave_interrupt_handler saved_interrupt_handler
287 
288  sigset_t set, oset;
289 
290  BLOCK_CHILD (set, oset);
291 
293 
294  octave_set_interrupt_handler (saved_interrupt_handler);
295 
296  UNBLOCK_CHILD (oset);
297 
299  }
300  break;
301 #endif
302 
303  case SIGFPE:
304  std::cerr << "warning: floating point exception" << std::endl;
305  break;
306 
307 #ifdef SIGPIPE
308  case SIGPIPE:
309  std::cerr << "warning: broken pipe" << std::endl;
310  break;
311 #endif
312  }
313  }
314  }
315 }
316 
317 static void
318 my_friendly_exit (const char *sig_name, int sig_number,
319  bool save_vars = true)
320 {
321  static bool been_there_done_that = false;
322 
323  if (been_there_done_that)
324  {
325 #if defined (SIGABRT)
326  octave_set_signal_handler (SIGABRT, SIG_DFL);
327 #endif
328 
329  std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";
330 
332 
333  abort ();
334  }
335  else
336  {
337  been_there_done_that = true;
338 
339  std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
340 
341  if (save_vars)
342  dump_octave_core ();
343 
344  if (sig_number < 0)
345  {
347 
348  exit (1);
349  }
350  else
351  {
352  octave_set_signal_handler (sig_number, SIG_DFL);
353 
354  GNULIB_NAMESPACE::raise (sig_number);
355  }
356  }
357 }
358 
359 sig_handler *
361  bool restart_syscalls)
362 {
363  struct sigaction act, oact;
364 
365  act.sa_handler = handler;
366  act.sa_flags = 0;
367 
368 #if defined (SIGALRM)
369  if (sig == SIGALRM)
370  {
371 #if defined (SA_INTERRUPT)
372  act.sa_flags |= SA_INTERRUPT;
373 #endif
374  }
375 #endif
376 #if defined (SA_RESTART)
377 #if defined (SIGALRM)
378  else
379 #endif
380  // FIXME: Do we also need to explicitly disable SA_RESTART?
381  if (restart_syscalls)
382  act.sa_flags |= SA_RESTART;
383 #endif
384 
385  GNULIB_NAMESPACE::sigemptyset (&act.sa_mask);
386  GNULIB_NAMESPACE::sigemptyset (&oact.sa_mask);
387 
388  GNULIB_NAMESPACE::sigaction (sig, &act, &oact);
389 
390  return oact.sa_handler;
391 }
392 
393 static void
395 {
396  my_friendly_exit (strsignal (sig), sig);
397 }
398 
399 // Handle SIGCHLD.
400 
401 #ifdef SIGCHLD
402 static void
403 sigchld_handler (int /* sig */)
404 {
406 
407  octave_signals_caught[SIGCHLD] = true;
408 }
409 #endif /* defined (SIGCHLD) */
410 
411 #ifdef SIGFPE
412 #if defined (__alpha__)
413 static void
414 sigfpe_handler (int /* sig */)
415 {
417  {
419 
420  octave_signals_caught[SIGFPE] = true;
421 
423  }
424 }
425 #endif /* defined (__alpha__) */
426 #endif /* defined (SIGFPE) */
427 
428 #if defined (SIGHUP) || defined (SIGTERM)
429 static void
430 sig_hup_or_term_handler (int sig)
431 {
432  switch (sig)
433  {
434 #if defined (SIGHUP)
435  case SIGHUP:
436  {
438  dump_octave_core ();
439  }
440  break;
441 #endif
442 
443 #if defined (SIGTERM)
444  case SIGTERM:
445  {
447  dump_octave_core ();
448  }
449  break;
450 #endif
451 
452  default:
453  break;
454  }
455 
456  clean_up_and_exit (0);
457 }
458 #endif
459 
460 #if 0
461 #if defined (SIGWINCH)
462 static void
463 sigwinch_handler (int /* sig */)
464 {
466 }
467 #endif
468 #endif
469 
470 // Handle SIGINT by restarting the parser (see octave.cc).
471 //
472 // This also has to work for SIGBREAK (on systems that have it), so we
473 // use the value of sig, instead of just assuming that it is called
474 // for SIGINT only.
475 
476 static void
477 user_abort (const char *sig_name, int sig_number)
478 {
479  if (! octave_initialized)
480  exit (1);
481 
482  if (can_interrupt)
483  {
485  {
487  {
490 
491  return;
492  }
493  else
494  {
495  // Clear the flag and do normal interrupt stuff.
496 
500  }
501  }
502 
504  {
505  if (octave_interrupt_state == 0)
507 
508 #if defined (__WIN32__) && ! defined (__CYGWIN__)
510 #else
512 #endif
513  }
514  else
515  {
516  // If we are already cleaning up from a previous interrupt,
517  // take note of the fact that another interrupt signal has
518  // arrived.
519 
520  if (octave_interrupt_state < 0)
522 
525 
527  && octave_interrupt_state == 2)
528  std::cerr << "Press Control-C again to abort." << std::endl;
529 
530  if (octave_interrupt_state >= 3)
531  my_friendly_exit (sig_name, sig_number, true);
532  }
533  }
534 
535 }
536 
537 static void
538 sigint_handler (int sig)
539 {
540 #if defined (__WIN32__) && ! defined (__CYGWIN__)
542 #else
543  user_abort (strsignal (sig), sig);
544 #endif
545 }
546 
547 #ifdef SIGPIPE
548 static void
549 sigpipe_handler (int /* sig */)
550 {
552 
553  octave_signals_caught[SIGPIPE] = true;
554 
555  // Don't loop forever on account of this.
556 
557  if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
559 }
560 #endif /* defined (SIGPIPE) */
561 
564 {
566 
567 #if defined (__WIN32__) && ! defined (__CYGWIN__)
568  w32_interrupt_manager::init ();
569 #endif
570 
571 #ifdef SIGINT
572  retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
573 #endif
574 
575 #ifdef SIGBREAK
576  retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
577 #endif
578 
579  return retval;
580 }
581 
584 {
586 
587 #if defined (__WIN32__) && ! defined (__CYGWIN__)
588  w32_interrupt_manager::init ();
589 #endif
590 
591 #ifdef SIGINT
592  retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
593 #endif
594 
595 #ifdef SIGBREAK
596  retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
597 #endif
598 
599  return retval;
600 }
601 
604  bool restart_syscalls)
605 {
607 
608 #if defined (__WIN32__) && ! defined (__CYGWIN__)
609  w32_interrupt_manager::init ();
610 #endif
611 
612 #ifdef SIGINT
613  retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
614  restart_syscalls);
615 #endif
616 
617 #ifdef SIGBREAK
618  retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
619  restart_syscalls);
620 #endif
621 
622  return retval;
623 }
624 
625 // Install all the handlers for the signals we might care about.
626 
627 void
629 {
630  for (int i = 0; i < NSIG; i++)
631  octave_signals_caught[i] = false;
632 
634 
635 #ifdef SIGABRT
637 #endif
638 
639 #ifdef SIGALRM
641 #endif
642 
643 #ifdef SIGBUS
645 #endif
646 
647 #ifdef SIGCHLD
648  octave_set_signal_handler (SIGCHLD, sigchld_handler);
649 #endif
650 
651  // SIGCLD
652  // SIGCONT
653 
654 #ifdef SIGEMT
656 #endif
657 
658 #ifdef SIGFPE
659 #if defined (__alpha__)
660  octave_set_signal_handler (SIGFPE, sigfpe_handler);
661 #else
663 #endif
664 #endif
665 
666 #ifdef SIGHUP
667  octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
668 #endif
669 
670 #ifdef SIGILL
672 #endif
673 
674  // SIGINFO
675  // SIGINT
676 
677 #ifdef SIGIOT
679 #endif
680 
681 #ifdef SIGLOST
683 #endif
684 
685 #ifdef SIGPIPE
686  octave_set_signal_handler (SIGPIPE, sigpipe_handler);
687 #endif
688 
689 #ifdef SIGPOLL
690  octave_set_signal_handler (SIGPOLL, SIG_IGN);
691 #endif
692 
693  // SIGPROF
694  // SIGPWR
695 
696 #ifdef SIGQUIT
698 #endif
699 
700 #ifdef SIGSEGV
702 #endif
703 
704  // SIGSTOP
705 
706 #ifdef SIGSYS
708 #endif
709 
710 #ifdef SIGTERM
711  octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
712 #endif
713 
714 #ifdef SIGTRAP
716 #endif
717 
718  // SIGTSTP
719  // SIGTTIN
720  // SIGTTOU
721  // SIGURG
722 
723 #ifdef SIGUSR1
725 #endif
726 
727 #ifdef SIGUSR2
729 #endif
730 
731 #ifdef SIGVTALRM
733 #endif
734 
735 #ifdef SIGIO
736  octave_set_signal_handler (SIGIO, SIG_IGN);
737 #endif
738 
739 #if 0
740 #ifdef SIGWINCH
741  octave_set_signal_handler (SIGWINCH, sigwinch_handler);
742 #endif
743 #endif
744 
745 #ifdef SIGXCPU
747 #endif
748 
749 #ifdef SIGXFSZ
751 #endif
752 
753 }
754 
755 static octave_scalar_map
757 {
759 
760 #ifdef SIGABRT
761  m.assign ("ABRT", SIGABRT);
762 #endif
763 
764 #ifdef SIGALRM
765  m.assign ("ALRM", SIGALRM);
766 #endif
767 
768 #ifdef SIGBUS
769  m.assign ("BUS", SIGBUS);
770 #endif
771 
772 #ifdef SIGCHLD
773  m.assign ("CHLD", SIGCHLD);
774 #endif
775 
776 #ifdef SIGCLD
777  m.assign ("CLD", SIGCLD);
778 #endif
779 
780 #ifdef SIGCONT
781  m.assign ("CONT", SIGCONT);
782 #endif
783 
784 #ifdef SIGEMT
785  m.assign ("EMT", SIGEMT);
786 #endif
787 
788 #ifdef SIGFPE
789  m.assign ("FPE", SIGFPE);
790 #endif
791 
792 #ifdef SIGHUP
793  m.assign ("HUP", SIGHUP);
794 #endif
795 
796 #ifdef SIGILL
797  m.assign ("ILL", SIGILL);
798 #endif
799 
800 #ifdef SIGINFO
801  m.assign ("INFO", SIGINFO);
802 #endif
803 
804 #ifdef SIGINT
805  m.assign ("INT", SIGINT);
806 #endif
807 
808 #ifdef SIGIO
809  m.assign ("IO", SIGIO);
810 #endif
811 
812 #ifdef SIGIOT
813  m.assign ("IOT", SIGIOT);
814 #endif
815 
816 #ifdef SIGKILL
817  m.assign ("KILL", SIGKILL);
818 #endif
819 
820 #ifdef SIGLOST
821  m.assign ("LOST", SIGLOST);
822 #endif
823 
824 #ifdef SIGPIPE
825  m.assign ("PIPE", SIGPIPE);
826 #endif
827 
828 #ifdef SIGPOLL
829  m.assign ("POLL", SIGPOLL);
830 #endif
831 
832 #ifdef SIGPROF
833  m.assign ("PROF", SIGPROF);
834 #endif
835 
836 #ifdef SIGPWR
837  m.assign ("PWR", SIGPWR);
838 #endif
839 
840 #ifdef SIGQUIT
841  m.assign ("QUIT", SIGQUIT);
842 #endif
843 
844 #ifdef SIGSEGV
845  m.assign ("SEGV", SIGSEGV);
846 #endif
847 
848 #ifdef SIGSTKFLT
849  m.assign ("STKFLT", SIGSTKFLT);
850 #endif
851 
852 #ifdef SIGSTOP
853  m.assign ("STOP", SIGSTOP);
854 #endif
855 
856 #ifdef SIGSYS
857  m.assign ("SYS", SIGSYS);
858 #endif
859 
860 #ifdef SIGTERM
861  m.assign ("TERM", SIGTERM);
862 #endif
863 
864 #ifdef SIGTRAP
865  m.assign ("TRAP", SIGTRAP);
866 #endif
867 
868 #ifdef SIGTSTP
869  m.assign ("TSTP", SIGTSTP);
870 #endif
871 
872 #ifdef SIGTTIN
873  m.assign ("TTIN", SIGTTIN);
874 #endif
875 
876 #ifdef SIGTTOU
877  m.assign ("TTOU", SIGTTOU);
878 #endif
879 
880 #ifdef SIGUNUSED
881  m.assign ("UNUSED", SIGUNUSED);
882 #endif
883 
884 #ifdef SIGURG
885  m.assign ("URG", SIGURG);
886 #endif
887 
888 #ifdef SIGUSR1
889  m.assign ("USR1", SIGUSR1);
890 #endif
891 
892 #ifdef SIGUSR2
893  m.assign ("USR2", SIGUSR2);
894 #endif
895 
896 #ifdef SIGVTALRM
897  m.assign ("VTALRM", SIGVTALRM);
898 #endif
899 
900 #ifdef SIGWINCH
901  m.assign ("WINCH", SIGWINCH);
902 #endif
903 
904 #ifdef SIGXCPU
905  m.assign ("XCPU", SIGXCPU);
906 #endif
907 
908 #ifdef SIGXFSZ
909  m.assign ("XFSZ", SIGXFSZ);
910 #endif
911 
912  return m;
913 }
914 
916 
917 bool
919 {
920  bool retval = true;
921 
922  if (! instance)
923  {
925 
926  if (instance)
928  }
929 
930  if (! instance)
931  {
932  ::error ("unable to create child list object!");
933 
934  retval = false;
935  }
936 
937  return retval;
938 }
939 
940 void
942 {
943  if (instance_ok ())
944  instance->insert (pid, f);
945 }
946 
947 void
949 {
950  if (instance_ok ())
951  instance->reap ();
952 }
953 
954 bool
956 {
957  return (instance_ok ()) ? instance->wait () : false;
958 }
959 
961 {
962 public:
963 
964  pid_equal (pid_t v) : val (v) { }
965 
966  bool operator () (const octave_child& oc) const { return oc.pid == val; }
967 
968 private:
969 
970  pid_t val;
971 };
972 
973 void
975 {
976  if (instance_ok ())
977  instance->remove_if (pid_equal (pid));
978 }
979 
980 #define OCL_REP octave_child_list::octave_child_list_rep
981 
982 void
983 OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
984 {
985  append (octave_child (pid, f));
986 }
987 
988 void
989 OCL_REP::reap (void)
990 {
991  // Mark the record for PID invalid.
992 
993  for (iterator p = begin (); p != end (); p++)
994  {
995  // The call to the octave_child::child_event_handler might
996  // invalidate the iterator (for example, by calling
997  // octave_child_list::remove), so we increment the iterator
998  // here.
999 
1000  octave_child& oc = *p;
1001 
1002  if (oc.have_status)
1003  {
1004  oc.have_status = 0;
1005 
1007 
1008  if (f && f (oc.pid, oc.status))
1009  oc.pid = -1;
1010  }
1011  }
1012 
1013  remove_if (pid_equal (-1));
1014 }
1015 
1016 // Wait on our children and record any changes in their status.
1017 
1018 bool
1019 OCL_REP::wait (void)
1020 {
1021  bool retval = false;
1022 
1023  for (iterator p = begin (); p != end (); p++)
1024  {
1025  octave_child& oc = *p;
1026 
1027  pid_t pid = oc.pid;
1028 
1029  if (pid > 0)
1030  {
1031  int status;
1032 
1033  if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
1034  {
1035  oc.have_status = 1;
1036 
1037  oc.status = status;
1038 
1039  retval = true;
1040 
1041  break;
1042  }
1043  }
1044  }
1045 
1046  return retval;
1047 }
1048 
1049 DEFUN (SIG, args, ,
1050  "-*- texinfo -*-\n\
1051 @deftypefn {Built-in Function} {} SIG ()\n\
1052 Return a structure containing Unix signal names and their defined values.\n\
1053 @end deftypefn")
1054 {
1055  octave_value retval;
1056 
1057  if (args.length () == 0)
1058  {
1059  static octave_scalar_map m = make_sig_struct ();
1060 
1061  retval = m;
1062  }
1063  else
1064  print_usage ();
1065 
1066  return retval;
1067 }
1068 
1069 /*
1070 %!assert (isstruct (SIG ()))
1071 %!assert (! isempty (SIG ()))
1072 
1073 %!error SIG (1)
1074 */
1075 
1076 DEFUN (debug_on_interrupt, args, nargout,
1077  "-*- texinfo -*-\n\
1078 @deftypefn {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
1079 @deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\
1080 @deftypefnx {Built-in Function} {} debug_on_interrupt (@var{new_val}, \"local\")\n\
1081 Query or set the internal variable that controls whether Octave will try\n\
1082 to enter debugging mode when it receives an interrupt signal (typically\n\
1083 generated with @kbd{C-c}).\n\
1084 \n\
1085 If a second interrupt signal is received before reaching the debugging mode,\n\
1086 a normal interrupt will occur.\n\
1087 \n\
1088 When called from inside a function with the @qcode{\"local\"} option, the\n\
1089 variable is changed locally for the function and any subroutines it calls.\n\
1090 The original variable value is restored when exiting the function.\n\
1091 @seealso{debug_on_error, debug_on_warning}\n\
1092 @end deftypefn")
1093 {
1094  return SET_INTERNAL_VARIABLE (debug_on_interrupt);
1095 }
1096 
1097 /*
1098 %!test
1099 %! orig_val = debug_on_interrupt ();
1100 %! old_val = debug_on_interrupt (! orig_val);
1101 %! assert (orig_val, old_val);
1102 %! assert (debug_on_interrupt (), ! orig_val);
1103 %! debug_on_interrupt (orig_val);
1104 %! assert (debug_on_interrupt (), orig_val);
1105 
1106 %!error (debug_on_interrupt (1, 2))
1107 */
1108 
1109 DEFUN (sighup_dumps_octave_core, args, nargout,
1110  "-*- texinfo -*-\n\
1111 @deftypefn {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
1112 @deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\
1113 @deftypefnx {Built-in Function} {} sighup_dumps_octave_core (@var{new_val}, \"local\")\n\
1114 Query or set the internal variable that controls whether Octave tries\n\
1115 to save all current variables to the file @file{octave-workspace} if it\n\
1116 receives a hangup signal.\n\
1117 \n\
1118 When called from inside a function with the @qcode{\"local\"} option, the\n\
1119 variable is changed locally for the function and any subroutines it calls.\n\
1120 The original variable value is restored when exiting the function.\n\
1121 @end deftypefn")
1122 {
1123  return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
1124 }
1125 
1126 /*
1127 %!test
1128 %! orig_val = sighup_dumps_octave_core ();
1129 %! old_val = sighup_dumps_octave_core (! orig_val);
1130 %! assert (orig_val, old_val);
1131 %! assert (sighup_dumps_octave_core (), ! orig_val);
1132 %! sighup_dumps_octave_core (orig_val);
1133 %! assert (sighup_dumps_octave_core (), orig_val);
1134 
1135 %!error (sighup_dumps_octave_core (1, 2))
1136 */
1137 
1138 DEFUN (sigterm_dumps_octave_core, args, nargout,
1139  "-*- texinfo -*-\n\
1140 @deftypefn {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
1141 @deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\
1142 @deftypefnx {Built-in Function} {} sigterm_dumps_octave_core (@var{new_val}, \"local\")\n\
1143 Query or set the internal variable that controls whether Octave tries\n\
1144 to save all current variables to the file @file{octave-workspace} if it\n\
1145 receives a terminate signal.\n\
1146 \n\
1147 When called from inside a function with the @qcode{\"local\"} option, the\n\
1148 variable is changed locally for the function and any subroutines it calls.\n\
1149 The original variable value is restored when exiting the function.\n\
1150 @end deftypefn")
1151 {
1152  return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
1153 }
1154 
1155 /*
1156 %!test
1157 %! orig_val = sigterm_dumps_octave_core ();
1158 %! old_val = sigterm_dumps_octave_core (! orig_val);
1159 %! assert (orig_val, old_val);
1160 %! assert (sigterm_dumps_octave_core (), ! orig_val);
1161 %! sigterm_dumps_octave_core (orig_val);
1162 %! assert (sigterm_dumps_octave_core (), orig_val);
1163 
1164 %!error (sigterm_dumps_octave_core (1, 2))
1165 */
char * strsignal(int code)
Definition: siglist.c:225
static bool wait(void)
Definition: sighandlers.cc:955
volatile sig_atomic_t octave_signal_caught
Definition: cquit.c:84
static void cleanup_instance(void)
Definition: sighandlers.h:179
octave_interrupt_handler octave_set_interrupt_handler(const volatile octave_interrupt_handler &h, bool restart_syscalls)
Definition: sighandlers.cc:603
static bool debug_mode
Definition: pt-eval.h:152
sig_atomic_t have_status
Definition: sighandlers.h:135
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
static bool have_breakpoints(void)
Definition: debug.h:102
static bool instance_ok(void)
Definition: sighandlers.cc:918
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
octave_interrupt_handler octave_catch_interrupts(void)
Definition: sighandlers.cc:563
bool forced_interactive
Definition: input.cc:107
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:120
#define WNOHANG
Definition: syscalls.cc:1938
#define UNBLOCK_CHILD(ovar)
Definition: sighandlers.cc:263
bool octave_initialized
Definition: toplev.cc:103
static void sigint_handler(int sig)
Definition: sighandlers.cc:538
void octave_jump_to_enclosing_context(void)
Definition: cquit.c:47
bool Vdebug_on_interrupt
Definition: sighandlers.cc:64
static void reap(void)
Definition: sighandlers.cc:948
static octave_child_list_rep * instance
Definition: sighandlers.h:177
std::list< octave_child >::iterator iterator
Definition: base-list.h:36
void install_signal_handlers(void)
Definition: sighandlers.cc:628
static pid_t waitpid(pid_t, int *status, int)
F77_RET_T const double const double * f
static void resize_terminal(void)
Definition: cmd-edit.cc:1147
bool interactive
Definition: input.cc:103
static bool octave_signals_caught[NSIG]
Definition: sighandlers.cc:75
#define MINGW_SIGNAL_CLEANUP()
Definition: sysdep.h:52
static void generic_sig_handler(int sig)
Definition: sighandlers.cc:394
#define BLOCK_CHILD(nvar, ovar)
Definition: sighandlers.cc:262
static void add(fptr f)
static bool Vsighup_dumps_octave_core
Definition: sighandlers.cc:69
static void insert(pid_t pid, octave_child::child_event_handler f)
Definition: sighandlers.cc:941
child_event_handler handler
Definition: sighandlers.h:132
void clean_up_and_exit(int status, bool safe_to_return)
Definition: toplev.cc:760
sig_atomic_t octave_interrupt_state
Definition: cquit.c:80
static void remove(pid_t pid)
Definition: sighandlers.cc:974
void insert(pid_t pid, octave_child::child_event_handler f)
Definition: sighandlers.cc:983
sig_atomic_t octave_interrupt_immediately
Definition: cquit.c:78
int pipe_handler_error_count
Definition: sighandlers.cc:58
bool can_interrupt
Definition: sighandlers.cc:61
void octave_signal_handler(void)
Definition: sighandlers.cc:269
octave_interrupt_handler octave_ignore_interrupts(void)
Definition: sighandlers.cc:583
pid_equal(pid_t v)
Definition: sighandlers.cc:964
static void user_abort(const char *sig_name, int sig_number)
Definition: sighandlers.cc:477
static bool Vsigterm_dumps_octave_core
Definition: sighandlers.cc:72
void remove_if(P pred)
Definition: base-list.h:50
void sig_handler(int)
Definition: sighandlers.h:46
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:225
bool octave_debug_on_interrupt_state
Definition: pt-bp.cc:33
static void my_friendly_exit(const char *sig_name, int sig_number, bool save_vars=true)
Definition: sighandlers.cc:318
bool(* child_event_handler)(pid_t, int)
Definition: sighandlers.h:105
bool operator()(const octave_child &oc) const
Definition: sighandlers.cc:966
sig_handler * octave_set_signal_handler(int sig, sig_handler *handler, bool restart_syscalls)
Definition: sighandlers.cc:360
bool Vdebugging
Definition: input.cc:117
static octave_scalar_map make_sig_struct(void)
Definition: sighandlers.cc:756
static size_t save_vars(std::ostream &os, const std::string &pattern, load_save_format fmt, bool save_as_floats)
Definition: load-save.cc:1026
static void dump_octave_core(std::ostream &os, const char *fname, load_save_format fmt, bool save_as_floats)
Definition: load-save.cc:1348