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