1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 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 <csignal>
31 #include <cstdlib>
32 
33 #include <iostream>
34 #include <new>
35 
36 #if defined (OCTAVE_USE_WINDOWS_API)
37 #  define WIN32_LEAN_AND_MEAN
38 #  include <windows.h>
39 #endif
40 
41 #include "child-list.h"
42 #include "cmd-edit.h"
43 #include "oct-syscalls.h"
44 #include "quit.h"
45 #include "signal-wrappers.h"
46 
47 #include "defun.h"
48 #include "error.h"
49 #include "input.h"
50 #include "interpreter-private.h"
51 #include "interpreter.h"
52 #include "load-save.h"
53 #include "octave.h"
54 #include "oct-map.h"
55 #include "pager.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.
65   int pipe_handler_error_count = 0;
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
my_friendly_exit(int sig,bool save_vars=true)88   my_friendly_exit (int sig, bool save_vars = true)
89   {
90     std::cerr << "fatal: caught signal "
91               << octave_strsignal_wrapper (sig)
92               << " -- stopping myself..." << std::endl;
93 
94     if (save_vars)
95       dump_octave_core ();
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
respond_to_pending_signals(void)106   respond_to_pending_signals (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     child_list& kids = __get_child_list__ ("respond_to_pending_signals");
190 
191     for (int sig = 0; sig < octave_num_signals (); sig++)
192       {
193         if (signals_caught[sig])
194           {
195             signals_caught[sig] = false;
196 
197             if ((have_sigchld && sig == sigchld)
198                 || (have_sigcld && sig == sigcld))
199               {
200                 // FIXME: should we block or ignore?
201                 volatile interrupt_handler saved_interrupt_handler
202                   = ignore_interrupts ();
203 
204                 void *context = octave_block_child ();
205 
206                 kids.wait ();
207 
208                 set_interrupt_handler (saved_interrupt_handler);
209 
210                 octave_unblock_child (context);
211 
212                 kids.reap ();
213               }
214             else if (have_sigpipe && sig == sigpipe)
215               {
216                 std::cerr << "warning: broken pipe" << std::endl;
217 
218                 // Don't loop forever on account of this.
219                 // FIXME: is this really needed?  Does it do anything
220                 // useful now?
221 
222                 if (pipe_handler_error_count++ > 100
223                     && octave_interrupt_state >= 0)
224                   octave_interrupt_state++;
225               }
226             else if (have_sighup && sig == sighup)
227               my_friendly_exit (sighup, Vsighup_dumps_octave_core);
228             else if (have_sigquit && sig == sigquit)
229               my_friendly_exit (sigquit, Vsigquit_dumps_octave_core);
230             else if (have_sigterm && sig == sigterm)
231               my_friendly_exit (sigterm, Vsigterm_dumps_octave_core);
232             else if ((have_sigalrm && sig == sigalrm)
233                      || (have_sigvtalrm && sig == sigvtalrm)
234                      || (have_sigio && sig == sigio)
235                      || (have_siglost && sig == siglost)
236                      || (have_sigxcpu && sig == sigxcpu)
237                      || (have_sigxfsz && sig == sigxfsz)
238                      || (have_sigusr1 && sig == sigusr1)
239                      || (have_sigusr2 && sig == sigusr2))
240               std::cerr << "warning: ignoring signal: "
241                         << octave_strsignal_wrapper (sig)
242                         << std::endl;
243             else if ((have_sigint && sig == sigint)
244                      || (have_sigbreak && sig == sigbreak))
245               ; // Handled separately; do nothing.
246             else
247               std::cerr << "warning: ignoring unexpected signal: "
248                         << octave_strsignal_wrapper (sig)
249                         << std::endl;
250           }
251       }
252   }
253 
254   sig_handler *
set_signal_handler(int sig,sig_handler * handler,bool restart_syscalls)255   set_signal_handler (int sig, sig_handler *handler, bool restart_syscalls)
256   {
257     return octave_set_signal_handler_internal (sig, handler, restart_syscalls);
258   }
259 
260   sig_handler *
set_signal_handler(const char * signame,sig_handler * handler,bool restart_syscalls)261   set_signal_handler (const char *signame, sig_handler *handler,
262                       bool restart_syscalls)
263   {
264     return octave_set_signal_handler_by_name (signame, handler,
265                                               restart_syscalls);
266   }
267 
268   static void
generic_sig_handler(int sig)269   generic_sig_handler (int sig)
270   {
271     // FIXME: this function may execute in a separate signal handler or
272     // signal watcher thread so it should probably be more careful about
273     // how it accesses global objects.
274 
275     octave_signal_caught = 1;
276 
277     signals_caught[sig] = true;
278 
279     static int sigint;
280     static const bool have_sigint
281       = octave_get_sig_number ("SIGINT", &sigint);
282 
283     static int sigbreak;
284     static const bool have_sigbreak
285       = octave_get_sig_number ("SIGBREAK", &sigbreak);
286 
287     if ((have_sigint && sig == sigint)
288         || (have_sigbreak && sig == sigbreak))
289       {
290         if (! octave_initialized)
291           exit (1);
292 
293         if (can_interrupt)
294           {
295             octave_signal_caught = 1;
296             octave_interrupt_state++;
297           }
298       }
299   }
300 
301   static void
deadly_sig_handler(int sig)302   deadly_sig_handler (int sig)
303   {
304     std::cerr << "fatal: caught signal "
305               << octave_strsignal_wrapper (sig)
306               << " -- stopping myself..." << std::endl;
307 
308     octave_set_default_signal_handler (sig);
309 
310     octave_raise_wrapper (sig);
311   }
312 
313   static void
fpe_sig_handler(int)314   fpe_sig_handler (int)
315   {
316     // FIXME: is there something better we can do?
317 
318     std::cerr << "warning: floating point exception" << std::endl;
319   }
320 
321   interrupt_handler
catch_interrupts(void)322   catch_interrupts (void)
323   {
324     interrupt_handler retval;
325 
326     retval.int_handler = set_signal_handler ("SIGINT", generic_sig_handler);
327     retval.brk_handler = set_signal_handler ("SIGBREAK", generic_sig_handler);
328 
329     return retval;
330   }
331 
332   interrupt_handler
ignore_interrupts(void)333   ignore_interrupts (void)
334   {
335     interrupt_handler retval;
336 
337     retval.int_handler = set_signal_handler ("SIGINT", SIG_IGN);
338     retval.brk_handler = set_signal_handler ("SIGBREAK", SIG_IGN);
339 
340     return retval;
341   }
342 
343   interrupt_handler
set_interrupt_handler(const volatile interrupt_handler & h,bool restart_syscalls)344   set_interrupt_handler (const volatile interrupt_handler& h,
345                          bool restart_syscalls)
346   {
347     interrupt_handler retval;
348 
349     retval.int_handler = set_signal_handler ("SIGINT", h.int_handler,
350                                              restart_syscalls);
351 
352     retval.brk_handler = set_signal_handler ("SIGBREAK", h.brk_handler,
353                                              restart_syscalls);
354 
355     return retval;
356   }
357 
358   // Install all the handlers for the signals we might care about.
359 
360   void
install_signal_handlers(void)361   install_signal_handlers (void)
362   {
363     if (! signals_caught)
364       signals_caught = new bool [octave_num_signals ()];
365 
366     for (int i = 0; i < octave_num_signals (); i++)
367       signals_caught[i] = false;
368 
369     // Interrupt signals.
370 
371     catch_interrupts ();
372 
373     // Program Error signals.  These are most likely unrecoverable for
374     // us.
375 
376     set_signal_handler ("SIGABRT", deadly_sig_handler);
377     set_signal_handler ("SIGBUS", deadly_sig_handler);
378     set_signal_handler ("SIGEMT", deadly_sig_handler);
379     set_signal_handler ("SIGILL", deadly_sig_handler);
380     // SIGIOT is normally another name for SIGABRT.
381     set_signal_handler ("SIGIOT", deadly_sig_handler);
382     set_signal_handler ("SIGSEGV", deadly_sig_handler);
383     set_signal_handler ("SIGSYS", deadly_sig_handler);
384     set_signal_handler ("SIGTRAP", deadly_sig_handler);
385 
386     // Handle SIGFPE separately.
387 
388     set_signal_handler ("SIGFPE", fpe_sig_handler);
389 
390     // Handle other signals for which the default action is to terminate
391     // the program.
392 
393     // Termination signals.
394 
395     set_signal_handler ("SIGHUP", generic_sig_handler);
396     set_signal_handler ("SIGQUIT", generic_sig_handler);
397     set_signal_handler ("SIGTERM", generic_sig_handler);
398 
399     // Alarm signals.
400 
401     set_signal_handler ("SIGALRM", generic_sig_handler);
402     set_signal_handler ("SIGVTALRM", generic_sig_handler);
403 
404     // I/O signals.
405 
406     set_signal_handler ("SIGLOST", generic_sig_handler);
407     set_signal_handler ("SIGPIPE", generic_sig_handler);
408 
409     // Job control signals.  We only recognize signals about child
410     // processes.
411 
412     set_signal_handler ("SIGCHLD", generic_sig_handler);
413     set_signal_handler ("SIGCLD", generic_sig_handler);
414 
415     // Resource limit signals.
416 
417     // FIXME: does it really make sense to try to handle the CPU limit
418     // signal?
419 
420     set_signal_handler ("SIGXCPU", generic_sig_handler);
421     set_signal_handler ("SIGXFSZ", generic_sig_handler);
422 
423     // User signals.
424 
425     set_signal_handler ("SIGUSR1", generic_sig_handler);
426     set_signal_handler ("SIGUSR2", generic_sig_handler);
427 
428     // This does nothing on Windows systems.
429     octave_create_interrupt_watcher_thread (generic_sig_handler);
430   }
431 
432   static void
set_sig_struct_field(octave_scalar_map & m,const char * signame)433   set_sig_struct_field (octave_scalar_map& m, const char *signame)
434   {
435     int signum;
436 
437     // The names in the struct do not include the leading "SIG" prefix.
438 
439     if (octave_get_sig_number (signame, &signum))
440       m.assign (&signame[3], signum);
441   }
442 
443   static octave_scalar_map
make_sig_struct(void)444   make_sig_struct (void)
445   {
446     octave_scalar_map m;
447 
448     set_sig_struct_field (m, "SIGABRT");
449     set_sig_struct_field (m, "SIGALRM");
450     set_sig_struct_field (m, "SIGBUS");
451     set_sig_struct_field (m, "SIGCHLD");
452     set_sig_struct_field (m, "SIGCLD");
453     set_sig_struct_field (m, "SIGCONT");
454     set_sig_struct_field (m, "SIGEMT");
455     set_sig_struct_field (m, "SIGFPE");
456     set_sig_struct_field (m, "SIGHUP");
457     set_sig_struct_field (m, "SIGILL");
458     set_sig_struct_field (m, "SIGINFO");
459     set_sig_struct_field (m, "SIGINT");
460     set_sig_struct_field (m, "SIGIO");
461     set_sig_struct_field (m, "SIGIOT");
462     set_sig_struct_field (m, "SIGKILL");
463     set_sig_struct_field (m, "SIGLOST");
464     set_sig_struct_field (m, "SIGPIPE");
465     set_sig_struct_field (m, "SIGPOLL");
466     set_sig_struct_field (m, "SIGPROF");
467     set_sig_struct_field (m, "SIGPWR");
468     set_sig_struct_field (m, "SIGQUIT");
469     set_sig_struct_field (m, "SIGSEGV");
470     set_sig_struct_field (m, "SIGSTKFLT");
471     set_sig_struct_field (m, "SIGSTOP");
472     set_sig_struct_field (m, "SIGSYS");
473     set_sig_struct_field (m, "SIGTERM");
474     set_sig_struct_field (m, "SIGTRAP");
475     set_sig_struct_field (m, "SIGTSTP");
476     set_sig_struct_field (m, "SIGTTIN");
477     set_sig_struct_field (m, "SIGTTOU");
478     set_sig_struct_field (m, "SIGUNUSED");
479     set_sig_struct_field (m, "SIGURG");
480     set_sig_struct_field (m, "SIGUSR1");
481     set_sig_struct_field (m, "SIGUSR2");
482     set_sig_struct_field (m, "SIGVTALRM");
483     set_sig_struct_field (m, "SIGWINCH");
484     set_sig_struct_field (m, "SIGXCPU");
485     set_sig_struct_field (m, "SIGXFSZ");
486 
487     return m;
488   }
489 }
490 
491 DEFUN (SIG, args, ,
492        doc: /* -*- texinfo -*-
493 @deftypefn {} {} SIG ()
494 Return a structure containing Unix signal names and their defined values.
495 @end deftypefn */)
496 {
497   if (args.length () != 0)
498     print_usage ();
499 
500   static octave_scalar_map m = octave::make_sig_struct ();
501 
502   return ovl (m);
503 }
504 
505 /*
506 %!assert (isstruct (SIG ()))
507 %!assert (! isempty (SIG ()))
508 
509 %!error SIG (1)
510 */
511 
512 DEFUN (debug_on_interrupt, args, nargout,
513        doc: /* -*- texinfo -*-
514 @deftypefn  {} {@var{val} =} debug_on_interrupt ()
515 @deftypefnx {} {@var{old_val} =} debug_on_interrupt (@var{new_val})
516 @deftypefnx {} {} debug_on_interrupt (@var{new_val}, "local")
517 Query or set the internal variable that controls whether Octave will try
518 to enter debugging mode when it receives an interrupt signal (typically
519 generated with @kbd{C-c}).
520 
521 If a second interrupt signal is received before reaching the debugging mode,
522 a normal interrupt will occur.
523 
524 When called from inside a function with the @qcode{"local"} option, the
525 variable is changed locally for the function and any subroutines it calls.
526 The original variable value is restored when exiting the function.
527 @seealso{debug_on_error, debug_on_warning}
528 @end deftypefn */)
529 {
530   return set_internal_variable (octave::Vdebug_on_interrupt, args, nargout,
531                                 "debug_on_interrupt");
532 }
533 
534 /*
535 %!test
536 %! orig_val = debug_on_interrupt ();
537 %! old_val = debug_on_interrupt (! orig_val);
538 %! assert (orig_val, old_val);
539 %! assert (debug_on_interrupt (), ! orig_val);
540 %! debug_on_interrupt (orig_val);
541 %! assert (debug_on_interrupt (), orig_val);
542 
543 %!error (debug_on_interrupt (1, 2))
544 */
545 
546 DEFUN (sighup_dumps_octave_core, args, nargout,
547        doc: /* -*- texinfo -*-
548 @deftypefn  {} {@var{val} =} sighup_dumps_octave_core ()
549 @deftypefnx {} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})
550 @deftypefnx {} {} sighup_dumps_octave_core (@var{new_val}, "local")
551 Query or set the internal variable that controls whether Octave tries
552 to save all current variables to the file @file{octave-workspace} if it
553 receives a hangup signal.
554 
555 When called from inside a function with the @qcode{"local"} option, the
556 variable is changed locally for the function and any subroutines it calls.
557 The original variable value is restored when exiting the function.
558 @end deftypefn */)
559 {
560   return set_internal_variable (octave::Vsighup_dumps_octave_core,
561                                 args, nargout,
562                                 "sighup_dumps_octave_core");
563 }
564 
565 /*
566 %!test
567 %! orig_val = sighup_dumps_octave_core ();
568 %! old_val = sighup_dumps_octave_core (! orig_val);
569 %! assert (orig_val, old_val);
570 %! assert (sighup_dumps_octave_core (), ! orig_val);
571 %! sighup_dumps_octave_core (orig_val);
572 %! assert (sighup_dumps_octave_core (), orig_val);
573 
574 %!error (sighup_dumps_octave_core (1, 2))
575 */
576 
577 DEFUN (sigquit_dumps_octave_core, args, nargout,
578        doc: /* -*- texinfo -*-
579 @deftypefn  {} {@var{val} =} sigquit_dumps_octave_core ()
580 @deftypefnx {} {@var{old_val} =} sigquit_dumps_octave_core (@var{new_val})
581 @deftypefnx {} {} sigquit_dumps_octave_core (@var{new_val}, "local")
582 Query or set the internal variable that controls whether Octave tries
583 to save all current variables to the file @file{octave-workspace} if it
584 receives a quit signal.
585 
586 When called from inside a function with the @qcode{"local"} option, the
587 variable is changed locally for the function and any subroutines it calls.
588 The original variable value is restored when exiting the function.
589 @end deftypefn */)
590 {
591   return set_internal_variable (octave::Vsigquit_dumps_octave_core,
592                                 args, nargout,
593                                 "sigquit_dumps_octave_core");
594 }
595 
596 /*
597 %!test
598 %! orig_val = sigquit_dumps_octave_core ();
599 %! old_val = sigquit_dumps_octave_core (! orig_val);
600 %! assert (orig_val, old_val);
601 %! assert (sigquit_dumps_octave_core (), ! orig_val);
602 %! sigquit_dumps_octave_core (orig_val);
603 %! assert (sigquit_dumps_octave_core (), orig_val);
604 
605 %!error (sigquit_dumps_octave_core (1, 2))
606 */
607 
608 DEFUN (sigterm_dumps_octave_core, args, nargout,
609        doc: /* -*- texinfo -*-
610 @deftypefn  {} {@var{val} =} sigterm_dumps_octave_core ()
611 @deftypefnx {} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})
612 @deftypefnx {} {} sigterm_dumps_octave_core (@var{new_val}, "local")
613 Query or set the internal variable that controls whether Octave tries
614 to save all current variables to the file @file{octave-workspace} if it
615 receives a terminate signal.
616 
617 When called from inside a function with the @qcode{"local"} option, the
618 variable is changed locally for the function and any subroutines it calls.
619 The original variable value is restored when exiting the function.
620 @end deftypefn */)
621 {
622   return set_internal_variable (octave::Vsigterm_dumps_octave_core,
623                                 args, nargout,
624                                 "sigterm_dumps_octave_core");
625 }
626 
627 /*
628 %!test
629 %! orig_val = sigterm_dumps_octave_core ();
630 %! old_val = sigterm_dumps_octave_core (! orig_val);
631 %! assert (orig_val, old_val);
632 %! assert (sigterm_dumps_octave_core (), ! orig_val);
633 %! sigterm_dumps_octave_core (orig_val);
634 %! assert (sigterm_dumps_octave_core (), orig_val);
635 
636 %!error (sigterm_dumps_octave_core (1, 2))
637 */
638