GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
sighandlers.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <csignal>
28 #include <cstdlib>
29 
30 #include <iostream>
31 #include <new>
32 
33 #if defined (OCTAVE_USE_WINDOWS_API)
34 # define WIN32_LEAN_AND_MEAN
35 # include <windows.h>
36 #endif
37 
38 #include "child-list.h"
39 #include "cmd-edit.h"
40 #include "oct-syscalls.h"
41 #include "quit.h"
42 #include "signal-wrappers.h"
43 
44 #include "bp-table.h"
45 #include "defun.h"
46 #include "error.h"
47 #include "input.h"
48 #include "interpreter-private.h"
49 #include "interpreter.h"
50 #include "load-save.h"
51 #include "octave.h"
52 #include "oct-map.h"
53 #include "pager.h"
54 #include "pt-bp.h"
55 #include "pt-eval.h"
56 #include "sighandlers.h"
57 #include "sysdep.h"
58 #include "utils.h"
59 #include "variables.h"
60 
61 namespace octave
62 {
63  // Nonzero means we have already printed a message for this series of
64  // SIGPIPES. We assume that the writer will eventually give up.
66 
67  // TRUE means we can be interrupted.
68  bool can_interrupt = false;
69 
70  // TRUE means we should try to enter the debugger on SIGINT.
71  bool Vdebug_on_interrupt = false;
72 
73  // Allow users to avoid writing octave-workspace for SIGHUP (sent by
74  // closing gnome-terminal, for example). Note that this variable has
75  // no effect if Vcrash_dumps_octave_core is FALSE.
76  static bool Vsighup_dumps_octave_core = true;
77 
78  // Similar to Vsighup_dumps_octave_core, but for SIGQUIT signal.
79  static bool Vsigquit_dumps_octave_core = true;
80 
81  // Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
82  static bool Vsigterm_dumps_octave_core = true;
83 
84  // List of signals we have caught since last call to signal_handler.
85  static bool *signals_caught = nullptr;
86 
87  static void
88  my_friendly_exit (int sig, bool save_vars = true)
89  {
90  std::cerr << "fatal: caught signal "
92  << " -- stopping myself..." << std::endl;
93 
94  if (save_vars)
96 
97  sysdep_cleanup ();
98 
99  throw exit_exception (1);
100  }
101 
102  // Called from octave_quit () to actually do something about the signals
103  // we have caught.
104 
105  void
107  {
108  // The list of signals is relatively short, so we will just go
109  // linearly through the list.
110 
111  // Interrupt signals are currently handled separately.
112 
113  static int sigint;
114  static const bool have_sigint
115  = octave_get_sig_number ("SIGINT", &sigint);
116 
117  static int sigbreak;
118  static const bool have_sigbreak
119  = octave_get_sig_number ("SIGBREAK", &sigbreak);
120 
121  // Termination signals.
122 
123  static int sighup;
124  static const bool have_sighup
125  = octave_get_sig_number ("SIGHUP", &sighup);
126 
127  static int sigquit;
128  static const bool have_sigquit
129  = octave_get_sig_number ("SIGQUIT", &sigquit);
130 
131  static int sigterm;
132  static const bool have_sigterm
133  = octave_get_sig_number ("SIGTERM", &sigterm);
134 
135  // Alarm signals.
136 
137  static int sigalrm;
138  static const bool have_sigalrm
139  = octave_get_sig_number ("SIGALRM", &sigalrm);
140 
141  static int sigvtalrm;
142  static const bool have_sigvtalrm
143  = octave_get_sig_number ("SIGVTALRM", &sigvtalrm);
144 
145  // I/O signals.
146 
147  static int sigio;
148  static const bool have_sigio
149  = octave_get_sig_number ("SIGIO", &sigio);
150 
151  static int siglost;
152  static const bool have_siglost
153  = octave_get_sig_number ("SIGLOST", &siglost);
154 
155  static int sigpipe;
156  static const bool have_sigpipe
157  = octave_get_sig_number ("SIGPIPE", &sigpipe);
158 
159  // Job control signals.
160 
161  static int sigchld;
162  static const bool have_sigchld
163  = octave_get_sig_number ("SIGCHLD", &sigchld);
164 
165  static int sigcld;
166  static const bool have_sigcld
167  = octave_get_sig_number ("SIGCLD", &sigcld);
168 
169  // Resource limit signals.
170 
171  static int sigxcpu;
172  static const bool have_sigxcpu
173  = octave_get_sig_number ("SIGXCPU", &sigxcpu);
174 
175  static int sigxfsz;
176  static const bool have_sigxfsz
177  = octave_get_sig_number ("SIGXFSZ", &sigxfsz);
178 
179  // User signals.
180 
181  static int sigusr1;
182  static const bool have_sigusr1
183  = octave_get_sig_number ("SIGUSR1", &sigusr1);
184 
185  static int sigusr2;
186  static const bool have_sigusr2
187  = octave_get_sig_number ("SIGUSR2", &sigusr2);
188 
189  octave::child_list& kids
190  = octave::__get_child_list__ ("respond_to_pending_signals");
191 
192  for (int sig = 0; sig < octave_num_signals (); sig++)
193  {
194  if (signals_caught[sig])
195  {
196  signals_caught[sig] = false;
197 
198  if ((have_sigchld && sig == sigchld)
199  || (have_sigcld && sig == sigcld))
200  {
201  // FIXME: should we block or ignore?
202  volatile interrupt_handler saved_interrupt_handler
203  = ignore_interrupts ();
204 
205  void *context = octave_block_child ();
206 
207  kids.wait ();
208 
209  set_interrupt_handler (saved_interrupt_handler);
210 
212 
213  kids.reap ();
214  }
215  else if (have_sigpipe && sig == sigpipe)
216  {
217  std::cerr << "warning: broken pipe" << std::endl;
218 
219  // Don't loop forever on account of this.
220  // FIXME: is this really needed? Does it do anything
221  // useful now?
222 
223  if (pipe_handler_error_count++ > 100
224  && octave_interrupt_state >= 0)
226  }
227  else if (have_sighup && sig == sighup)
229  else if (have_sigquit && sig == sigquit)
231  else if (have_sigterm && sig == sigterm)
233  else if ((have_sigalrm && sig == sigalrm)
234  || (have_sigvtalrm && sig == sigvtalrm)
235  || (have_sigio && sig == sigio)
236  || (have_siglost && sig == siglost)
237  || (have_sigxcpu && sig == sigxcpu)
238  || (have_sigxfsz && sig == sigxfsz)
239  || (have_sigusr1 && sig == sigusr1)
240  || (have_sigusr2 && sig == sigusr2))
241  std::cerr << "warning: ignoring signal: "
242  << octave_strsignal_wrapper (sig)
243  << std::endl;
244  else if ((have_sigint && sig == sigint)
245  || (have_sigbreak && sig == sigbreak))
246  ; // Handled separately; do nothing.
247  else
248  std::cerr << "warning: ignoring unexpected signal: "
249  << octave_strsignal_wrapper (sig)
250  << std::endl;
251  }
252  }
253  }
254 
255  sig_handler *
256  set_signal_handler (int sig, sig_handler *handler, bool restart_syscalls)
257  {
258  return octave_set_signal_handler_internal (sig, handler, restart_syscalls);
259  }
260 
261  sig_handler *
262  set_signal_handler (const char *signame, sig_handler *handler,
263  bool restart_syscalls)
264  {
265  return octave_set_signal_handler_by_name (signame, handler,
266  restart_syscalls);
267  }
268 
269  static void
271  {
272  // FIXME: this function may execute in a separate signal handler or
273  // signal watcher thread so it should probably be more careful about
274  // how it accesses global objects.
275 
277 
278  signals_caught[sig] = true;
279 
280  static int sigint;
281  static const bool have_sigint
282  = octave_get_sig_number ("SIGINT", &sigint);
283 
284  static int sigbreak;
285  static const bool have_sigbreak
286  = octave_get_sig_number ("SIGBREAK", &sigbreak);
287 
288  if ((have_sigint && sig == sigint)
289  || (have_sigbreak && sig == sigbreak))
290  {
291  if (! octave_initialized)
292  exit (1);
293 
294  if (can_interrupt)
295  {
298  }
299  }
300  }
301 
302  static void
304  {
305  std::cerr << "fatal: caught signal "
306  << octave_strsignal_wrapper (sig)
307  << " -- stopping myself..." << std::endl;
308 
310 
311  octave_raise_wrapper (sig);
312  }
313 
314  static void
316  {
317  // FIXME: is there something better we can do?
318 
319  std::cerr << "warning: floating point exception" << std::endl;
320  }
321 
322  interrupt_handler
324  {
326 
327  retval.int_handler = set_signal_handler ("SIGINT", generic_sig_handler);
328  retval.brk_handler = set_signal_handler ("SIGBREAK", generic_sig_handler);
329 
330  return retval;
331  }
332 
333  interrupt_handler
335  {
337 
338  retval.int_handler = set_signal_handler ("SIGINT", SIG_IGN);
339  retval.brk_handler = set_signal_handler ("SIGBREAK", SIG_IGN);
340 
341  return retval;
342  }
343 
344  interrupt_handler
346  bool restart_syscalls)
347  {
349 
350  retval.int_handler = set_signal_handler ("SIGINT", h.int_handler,
351  restart_syscalls);
352 
353  retval.brk_handler = set_signal_handler ("SIGBREAK", h.brk_handler,
354  restart_syscalls);
355 
356  return retval;
357  }
358 
359  // Install all the handlers for the signals we might care about.
360 
361  void
363  {
364  if (! signals_caught)
365  signals_caught = new bool [octave_num_signals ()];
366 
367  for (int i = 0; i < octave_num_signals (); i++)
368  signals_caught[i] = false;
369 
370  // Interrupt signals.
371 
372  catch_interrupts ();
373 
374  // Program Error signals. These are most likely unrecoverable for
375  // us.
376 
381  // SIGIOT is normally another name for SIGABRT.
386 
387  // Handle SIGFPE separately.
388 
390 
391  // Handle other signals for which the default action is to terminate
392  // the program.
393 
394  // Termination signals.
395 
399 
400  // Alarm signals.
401 
404 
405  // I/O signals.
406 
409 
410  // Job control signals. We only recognize signals about child
411  // processes.
412 
415 
416  // Resource limit signals.
417 
418  // FIXME: does it really make sense to try to handle the CPU limit
419  // signal?
420 
423 
424  // User signals.
425 
428 
429  // This does nothing on Windows systems.
431  }
432 
433  static void
434  set_sig_struct_field (octave_scalar_map& m, const char *signame)
435  {
436  int signum;
437 
438  // The names in the struct do not include the leading "SIG" prefix.
439 
440  if (octave_get_sig_number (signame, &signum))
441  m.assign (&signame[3], signum);
442  }
443 
444  static octave_scalar_map
446  {
448 
449  set_sig_struct_field (m, "SIGABRT");
450  set_sig_struct_field (m, "SIGALRM");
451  set_sig_struct_field (m, "SIGBUS");
452  set_sig_struct_field (m, "SIGCHLD");
453  set_sig_struct_field (m, "SIGCLD");
454  set_sig_struct_field (m, "SIGCONT");
455  set_sig_struct_field (m, "SIGEMT");
456  set_sig_struct_field (m, "SIGFPE");
457  set_sig_struct_field (m, "SIGHUP");
458  set_sig_struct_field (m, "SIGILL");
459  set_sig_struct_field (m, "SIGINFO");
460  set_sig_struct_field (m, "SIGINT");
461  set_sig_struct_field (m, "SIGIO");
462  set_sig_struct_field (m, "SIGIOT");
463  set_sig_struct_field (m, "SIGKILL");
464  set_sig_struct_field (m, "SIGLOST");
465  set_sig_struct_field (m, "SIGPIPE");
466  set_sig_struct_field (m, "SIGPOLL");
467  set_sig_struct_field (m, "SIGPROF");
468  set_sig_struct_field (m, "SIGPWR");
469  set_sig_struct_field (m, "SIGQUIT");
470  set_sig_struct_field (m, "SIGSEGV");
471  set_sig_struct_field (m, "SIGSTKFLT");
472  set_sig_struct_field (m, "SIGSTOP");
473  set_sig_struct_field (m, "SIGSYS");
474  set_sig_struct_field (m, "SIGTERM");
475  set_sig_struct_field (m, "SIGTRAP");
476  set_sig_struct_field (m, "SIGTSTP");
477  set_sig_struct_field (m, "SIGTTIN");
478  set_sig_struct_field (m, "SIGTTOU");
479  set_sig_struct_field (m, "SIGUNUSED");
480  set_sig_struct_field (m, "SIGURG");
481  set_sig_struct_field (m, "SIGUSR1");
482  set_sig_struct_field (m, "SIGUSR2");
483  set_sig_struct_field (m, "SIGVTALRM");
484  set_sig_struct_field (m, "SIGWINCH");
485  set_sig_struct_field (m, "SIGXCPU");
486  set_sig_struct_field (m, "SIGXFSZ");
487 
488  return m;
489  }
490 }
491 
492 DEFUN (SIG, args, ,
493  doc: /* -*- texinfo -*-
494 @deftypefn {} {} SIG ()
495 Return a structure containing Unix signal names and their defined values.
496 @end deftypefn */)
497 {
498  if (args.length () != 0)
499  print_usage ();
500 
502 
503  return ovl (m);
504 }
505 
506 /*
507 %!assert (isstruct (SIG ()))
508 %!assert (! isempty (SIG ()))
509 
510 %!error SIG (1)
511 */
512 
513 DEFUN (debug_on_interrupt, args, nargout,
514  doc: /* -*- texinfo -*-
515 @deftypefn {} {@var{val} =} debug_on_interrupt ()
516 @deftypefnx {} {@var{old_val} =} debug_on_interrupt (@var{new_val})
517 @deftypefnx {} {} debug_on_interrupt (@var{new_val}, "local")
518 Query or set the internal variable that controls whether Octave will try
519 to enter debugging mode when it receives an interrupt signal (typically
520 generated with @kbd{C-c}).
521 
522 If a second interrupt signal is received before reaching the debugging mode,
523 a normal interrupt will occur.
524 
525 When called from inside a function with the @qcode{"local"} option, the
526 variable is changed locally for the function and any subroutines it calls.
527 The original variable value is restored when exiting the function.
528 @seealso{debug_on_error, debug_on_warning}
529 @end deftypefn */)
530 {
532  "debug_on_interrupt");
533 }
534 
535 /*
536 %!test
537 %! orig_val = debug_on_interrupt ();
538 %! old_val = debug_on_interrupt (! orig_val);
539 %! assert (orig_val, old_val);
540 %! assert (debug_on_interrupt (), ! orig_val);
541 %! debug_on_interrupt (orig_val);
542 %! assert (debug_on_interrupt (), orig_val);
543 
544 %!error (debug_on_interrupt (1, 2))
545 */
546 
547 DEFUN (sighup_dumps_octave_core, args, nargout,
548  doc: /* -*- texinfo -*-
549 @deftypefn {} {@var{val} =} sighup_dumps_octave_core ()
550 @deftypefnx {} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})
551 @deftypefnx {} {} sighup_dumps_octave_core (@var{new_val}, "local")
552 Query or set the internal variable that controls whether Octave tries
553 to save all current variables to the file @file{octave-workspace} if it
554 receives a hangup signal.
555 
556 When called from inside a function with the @qcode{"local"} option, the
557 variable is changed locally for the function and any subroutines it calls.
558 The original variable value is restored when exiting the function.
559 @end deftypefn */)
560 {
562  args, nargout,
563  "sighup_dumps_octave_core");
564 }
565 
566 /*
567 %!test
568 %! orig_val = sighup_dumps_octave_core ();
569 %! old_val = sighup_dumps_octave_core (! orig_val);
570 %! assert (orig_val, old_val);
571 %! assert (sighup_dumps_octave_core (), ! orig_val);
572 %! sighup_dumps_octave_core (orig_val);
573 %! assert (sighup_dumps_octave_core (), orig_val);
574 
575 %!error (sighup_dumps_octave_core (1, 2))
576 */
577 
578 DEFUN (sigquit_dumps_octave_core, args, nargout,
579  doc: /* -*- texinfo -*-
580 @deftypefn {} {@var{val} =} sigquit_dumps_octave_core ()
581 @deftypefnx {} {@var{old_val} =} sigquit_dumps_octave_core (@var{new_val})
582 @deftypefnx {} {} sigquit_dumps_octave_core (@var{new_val}, "local")
583 Query or set the internal variable that controls whether Octave tries
584 to save all current variables to the file @file{octave-workspace} if it
585 receives a quit signal.
586 
587 When called from inside a function with the @qcode{"local"} option, the
588 variable is changed locally for the function and any subroutines it calls.
589 The original variable value is restored when exiting the function.
590 @end deftypefn */)
591 {
593  args, nargout,
594  "sigquit_dumps_octave_core");
595 }
596 
597 /*
598 %!test
599 %! orig_val = sigquit_dumps_octave_core ();
600 %! old_val = sigquit_dumps_octave_core (! orig_val);
601 %! assert (orig_val, old_val);
602 %! assert (sigquit_dumps_octave_core (), ! orig_val);
603 %! sigquit_dumps_octave_core (orig_val);
604 %! assert (sigquit_dumps_octave_core (), orig_val);
605 
606 %!error (sigquit_dumps_octave_core (1, 2))
607 */
608 
609 DEFUN (sigterm_dumps_octave_core, args, nargout,
610  doc: /* -*- texinfo -*-
611 @deftypefn {} {@var{val} =} sigterm_dumps_octave_core ()
612 @deftypefnx {} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})
613 @deftypefnx {} {} sigterm_dumps_octave_core (@var{new_val}, "local")
614 Query or set the internal variable that controls whether Octave tries
615 to save all current variables to the file @file{octave-workspace} if it
616 receives a terminate signal.
617 
618 When called from inside a function with the @qcode{"local"} option, the
619 variable is changed locally for the function and any subroutines it calls.
620 The original variable value is restored when exiting the function.
621 @end deftypefn */)
622 {
624  args, nargout,
625  "sigterm_dumps_octave_core");
626 }
627 
628 /*
629 %!test
630 %! orig_val = sigterm_dumps_octave_core ();
631 %! old_val = sigterm_dumps_octave_core (! orig_val);
632 %! assert (orig_val, old_val);
633 %! assert (sigterm_dumps_octave_core (), ! orig_val);
634 %! sigterm_dumps_octave_core (orig_val);
635 %! assert (sigterm_dumps_octave_core (), orig_val);
636 
637 %!error (sigterm_dumps_octave_core (1, 2))
638 */
volatile sig_atomic_t octave_signal_caught
Definition: cquit.c:49
bool octave_initialized
Definition: interpreter.cc:84
child_list & __get_child_list__(const std::string &who)
octave_sig_handler * octave_set_default_signal_handler(int sig)
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
interrupt_handler catch_interrupts(void)
Definition: sighandlers.cc:323
octave_sig_handler * octave_set_signal_handler_internal(int sig, octave_sig_handler *handler, bool restart_syscalls)
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void sig_handler(int)
Definition: sighandlers.h:43
void * octave_block_child(void)
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:79
void sysdep_cleanup(void)
Definition: sysdep.cc:337
static octave_scalar_map make_sig_struct(void)
Definition: sighandlers.cc:445
void respond_to_pending_signals(void)
Definition: sighandlers.cc:106
bool can_interrupt
Definition: sighandlers.cc:68
sig_handler * set_signal_handler(int sig, sig_handler *handler, bool restart_syscalls)
Definition: sighandlers.cc:256
double h
Definition: graphics.cc:11808
void octave_unblock_child(void *context_arg)
bool Vdebug_on_interrupt
Definition: sighandlers.cc:71
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
int pipe_handler_error_count
Definition: sighandlers.cc:65
void octave_create_interrupt_watcher_thread(octave_sig_handler *handler)
double signum(double x)
Definition: lo-mappers.h:244
bool wait(void)
Definition: child-list.cc:83
static void set_sig_struct_field(octave_scalar_map &m, const char *signame)
Definition: sighandlers.cc:434
octave_value retval
Definition: data.cc:6246
sig_atomic_t octave_interrupt_state
Definition: cquit.c:32
int octave_num_signals(void)
interrupt_handler ignore_interrupts(void)
Definition: sighandlers.cc:334
static void my_friendly_exit(int sig, bool save_vars=true)
Definition: sighandlers.cc:88
end deftypefn *return set_internal_variable(Vsvd_driver, args, nargout, "svd_driver", driver_names)
static bool Vsigquit_dumps_octave_core
Definition: sighandlers.cc:79
int octave_raise_wrapper(int signum)
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
static void deadly_sig_handler(int sig)
Definition: sighandlers.cc:303
static bool Vsigterm_dumps_octave_core
Definition: sighandlers.cc:82
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:227
static bool Vsighup_dumps_octave_core
Definition: sighandlers.cc:76
interrupt_handler set_interrupt_handler(const volatile interrupt_handler &h, bool restart_syscalls)
Definition: sighandlers.cc:345
static bool * signals_caught
Definition: sighandlers.cc:85
for i
Definition: data.cc:5264
bool octave_get_sig_number(const char *signame, int *signum)
octave_sig_handler * octave_set_signal_handler_by_name(const char *signame, octave_sig_handler *handler, bool restart_syscalls)
static void fpe_sig_handler(int)
Definition: sighandlers.cc:315
static void generic_sig_handler(int sig)
Definition: sighandlers.cc:270
void reap(void)
Definition: child-list.cc:55
void install_signal_handlers(void)
Definition: sighandlers.cc:362
static size_t save_vars(std::ostream &os, const std::string &pattern, load_save_format fmt, bool save_as_floats)
Definition: load-save.cc:1016
static void dump_octave_core(std::ostream &os, const char *fname, load_save_format fmt, bool save_as_floats)
Definition: load-save.cc:1336
char * octave_strsignal_wrapper(int signum)