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