Mercurial > hg > octave-lyh
annotate src/sighandlers.cc @ 8920:eb63fbe60fab
update copyright notices
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 07 Mar 2009 10:41:27 -0500 |
parents | 73c4516fae10 |
children | 829e69ec3110 |
rev | line source |
---|---|
1 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, |
8920 | 4 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton |
1 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
1 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
1 | 21 |
22 */ | |
23 | |
240 | 24 #ifdef HAVE_CONFIG_H |
1230 | 25 #include <config.h> |
1 | 26 #endif |
27 | |
2536 | 28 #include <cstdlib> |
29 | |
3503 | 30 #include <iostream> |
1344 | 31 #include <new> |
32 | |
1350 | 33 #ifdef HAVE_UNISTD_H |
2442 | 34 #ifdef HAVE_SYS_TYPES_H |
834 | 35 #include <sys/types.h> |
2442 | 36 #endif |
834 | 37 #include <unistd.h> |
38 #endif | |
1343 | 39 |
3281 | 40 #include "cmd-edit.h" |
5453 | 41 #include "oct-syscalls.h" |
4153 | 42 #include "quit.h" |
3281 | 43 |
8658
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
44 #include "debug.h" |
4185 | 45 #include "defun.h" |
1352 | 46 #include "error.h" |
1373 | 47 #include "load-save.h" |
4294 | 48 #include "oct-map.h" |
2091 | 49 #include "pager.h" |
4185 | 50 #include "pt-bp.h" |
8658
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
51 #include "pt-eval.h" |
1 | 52 #include "sighandlers.h" |
4787 | 53 #include "sysdep.h" |
1352 | 54 #include "syswait.h" |
2091 | 55 #include "toplev.h" |
1 | 56 #include "utils.h" |
5794 | 57 #include "variables.h" |
1 | 58 |
59 // Nonzero means we have already printed a message for this series of | |
60 // SIGPIPES. We assume that the writer will eventually give up. | |
61 int pipe_handler_error_count = 0; | |
62 | |
3018 | 63 // TRUE means we can be interrupted. |
64 bool can_interrupt = false; | |
1 | 65 |
4185 | 66 // TRUE means we should try to enter the debugger on SIGINT. |
67 static bool Vdebug_on_interrupt = false; | |
68 | |
4449 | 69 // Allow users to avoid writing octave-core for SIGHUP (sent by |
70 // closing gnome-terminal, for example). Note that this variable has | |
71 // no effect if Vcrash_dumps_octave_core is FALSE. | |
5794 | 72 static bool Vsighup_dumps_octave_core = true; |
4449 | 73 |
74 // Similar to Vsighup_dumps_octave_core, but for SIGTERM signal. | |
5794 | 75 static bool Vsigterm_dumps_octave_core = true; |
4449 | 76 |
6098 | 77 #if defined (RETSIGTYPE_IS_VOID) |
2469 | 78 #define SIGHANDLER_RETURN(status) return |
79 #else | |
80 #define SIGHANDLER_RETURN(status) return status | |
81 #endif | |
82 | |
2554 | 83 #if defined (MUST_REINSTALL_SIGHANDLERS) |
84 #define MAYBE_REINSTALL_SIGHANDLER(sig, handler) \ | |
85 octave_set_signal_handler (sig, handler) | |
2931 | 86 #define REINSTALL_USES_SIG 1 |
2554 | 87 #else |
88 #define MAYBE_REINSTALL_SIGHANDLER(sig, handler) \ | |
89 do { } while (0) | |
90 #endif | |
91 | |
92 #if defined (__EMX__) | |
2626 | 93 #define MAYBE_ACK_SIGNAL(sig) \ |
2554 | 94 octave_set_signal_handler (sig, SIG_ACK) |
2931 | 95 #define ACK_USES_SIG 1 |
2554 | 96 #else |
2626 | 97 #define MAYBE_ACK_SIGNAL(sig) \ |
2554 | 98 do { } while (0) |
99 #endif | |
100 | |
5142 | 101 // List of signals we have caught since last call to octave_signal_handler. |
102 static bool octave_signals_caught[NSIG]; | |
103 | |
104 // Called from OCTAVE_QUIT to actually do something about the signals | |
105 // we have caught. | |
106 | |
107 void | |
108 octave_signal_handler (void) | |
109 { | |
110 // The list of signals is relatively short, so we will just go | |
111 // linearly through the list. | |
112 | |
113 for (int i = 0; i < NSIG; i++) | |
114 { | |
115 if (octave_signals_caught[i]) | |
116 { | |
117 octave_signals_caught[i] = false; | |
118 | |
119 switch (i) | |
120 { | |
5451 | 121 #ifdef SIGCHLD |
5142 | 122 case SIGCHLD: |
123 octave_child_list::reap (); | |
124 break; | |
5451 | 125 #endif |
5142 | 126 |
127 case SIGFPE: | |
128 std::cerr << "warning: floating point exception -- trying to return to prompt" << std::endl; | |
129 break; | |
130 | |
5451 | 131 #ifdef SIGPIPE |
5142 | 132 case SIGPIPE: |
133 std::cerr << "warning: broken pipe -- some output may be lost" << std::endl; | |
134 break; | |
5451 | 135 #endif |
5142 | 136 } |
137 } | |
138 } | |
139 } | |
140 | |
1 | 141 static void |
4787 | 142 my_friendly_exit (const char *sig_name, int sig_number, |
143 bool save_vars = true) | |
1 | 144 { |
2536 | 145 static bool been_there_done_that = false; |
146 | |
147 if (been_there_done_that) | |
148 { | |
2554 | 149 #if defined (SIGABRT) |
2536 | 150 octave_set_signal_handler (SIGABRT, SIG_DFL); |
151 #endif | |
152 | |
3644 | 153 std::cerr << "panic: attempted clean up apparently failed -- aborting...\n"; |
5451 | 154 |
155 MINGW_SIGNAL_CLEANUP (); | |
156 | |
2536 | 157 abort (); |
158 } | |
159 else | |
160 { | |
161 been_there_done_that = true; | |
1373 | 162 |
3644 | 163 std::cerr << "panic: " << sig_name << " -- stopping myself...\n"; |
2536 | 164 |
4787 | 165 if (save_vars) |
4791 | 166 dump_octave_core (); |
2536 | 167 |
3162 | 168 if (sig_number < 0) |
5451 | 169 { |
170 MINGW_SIGNAL_CLEANUP (); | |
171 | |
172 exit (1); | |
173 } | |
3162 | 174 else |
175 { | |
176 octave_set_signal_handler (sig_number, SIG_DFL); | |
177 | |
4092 | 178 #if defined (HAVE_RAISE) |
179 raise (sig_number); | |
180 #elif defined (HAVE_KILL) | |
3162 | 181 kill (getpid (), sig_number); |
4092 | 182 #else |
183 exit (1); | |
184 #endif | |
3162 | 185 } |
4092 | 186 |
2536 | 187 } |
1 | 188 } |
189 | |
1446 | 190 sig_handler * |
5770 | 191 octave_set_signal_handler (int sig, sig_handler *handler, |
192 bool restart_syscalls) | |
1446 | 193 { |
194 #if defined (HAVE_POSIX_SIGNALS) | |
195 struct sigaction act, oact; | |
5144 | 196 |
1446 | 197 act.sa_handler = handler; |
198 act.sa_flags = 0; | |
5144 | 199 |
200 if (sig == SIGALRM) | |
201 { | |
202 #if defined (SA_INTERRUPT) | |
203 act.sa_flags |= SA_INTERRUPT; | |
204 #endif | |
205 } | |
206 #if defined (SA_RESTART) | |
5775 | 207 // FIXME -- Do we also need to explicitly disable SA_RESTART? |
5770 | 208 else if (restart_syscalls) |
209 act.sa_flags |= SA_RESTART; | |
5144 | 210 #endif |
211 | |
1446 | 212 sigemptyset (&act.sa_mask); |
213 sigemptyset (&oact.sa_mask); | |
5144 | 214 |
1446 | 215 sigaction (sig, &act, &oact); |
5144 | 216 |
1446 | 217 return oact.sa_handler; |
218 #else | |
219 return signal (sig, handler); | |
220 #endif | |
221 } | |
222 | |
1 | 223 static RETSIGTYPE |
1446 | 224 generic_sig_handler (int sig) |
1 | 225 { |
5844 | 226 my_friendly_exit (strsignal (sig), sig); |
1 | 227 |
2469 | 228 SIGHANDLER_RETURN (0); |
1 | 229 } |
230 | |
2091 | 231 // Handle SIGCHLD. |
1230 | 232 |
4064 | 233 #ifdef SIGCHLD |
1230 | 234 static RETSIGTYPE |
2092 | 235 sigchld_handler (int /* sig */) |
1230 | 236 { |
2705 | 237 volatile octave_interrupt_handler saved_interrupt_handler |
2554 | 238 = octave_ignore_interrupts (); |
239 | |
2626 | 240 // I wonder if this is really right, or if SIGCHLD should just be |
241 // blocked on OS/2 systems the same as for systems with POSIX signal | |
242 // functions. | |
243 | |
244 #if defined (__EMX__) | |
2554 | 245 volatile sig_handler *saved_sigchld_handler |
2626 | 246 = octave_set_signal_handler (SIGCHLD, SIG_IGN); |
2554 | 247 #endif |
248 | |
2626 | 249 sigset_t set, oset; |
250 | |
251 BLOCK_CHILD (set, oset); | |
252 | |
5142 | 253 if (octave_child_list::wait ()) |
2554 | 254 { |
5142 | 255 // The status of some child changed. |
2209 | 256 |
5142 | 257 octave_signal_caught = 1; |
2197 | 258 |
5142 | 259 octave_signals_caught[SIGCHLD] = true; |
1230 | 260 } |
2469 | 261 |
2600 | 262 octave_set_interrupt_handler (saved_interrupt_handler); |
2554 | 263 |
2626 | 264 UNBLOCK_CHILD (oset); |
265 | |
266 #ifdef __EMX__ | |
2554 | 267 octave_set_signal_handler (SIGCHLD, saved_sigchld_handler); |
2475 | 268 #endif |
269 | |
2626 | 270 MAYBE_ACK_SIGNAL (SIGCHLD); |
2554 | 271 |
272 MAYBE_REINSTALL_SIGHANDLER (SIGCHLD, sigchld_handler); | |
273 | |
2469 | 274 SIGHANDLER_RETURN (0); |
1230 | 275 } |
4064 | 276 #endif /* defined(SIGCHLD) */ |
1230 | 277 |
4064 | 278 #ifdef SIGFPE |
1373 | 279 #if defined (__alpha__) |
280 static RETSIGTYPE | |
1488 | 281 sigfpe_handler (int /* sig */) |
1373 | 282 { |
2626 | 283 MAYBE_ACK_SIGNAL (SIGFPE); |
2554 | 284 |
285 MAYBE_REINSTALL_SIGHANDLER (SIGFPE, sigfpe_handler); | |
1373 | 286 |
5142 | 287 if (can_interrupt && octave_interrupt_state >= 0) |
288 { | |
289 octave_signal_caught = 1; | |
1373 | 290 |
5142 | 291 octave_signals_caught[SIGFPE] = true; |
4182 | 292 |
5142 | 293 octave_interrupt_state++; |
294 } | |
1373 | 295 |
2469 | 296 SIGHANDLER_RETURN (0); |
1373 | 297 } |
4064 | 298 #endif /* defined(__alpha__) */ |
299 #endif /* defined(SIGFPE) */ | |
1373 | 300 |
4449 | 301 #if defined (SIGHUP) || defined (SIGTERM) |
302 static RETSIGTYPE | |
303 sig_hup_or_term_handler (int sig) | |
304 { | |
305 MAYBE_ACK_SIGNAL (sig); | |
306 | |
307 MAYBE_REINSTALL_SIGHANDLER (sig, sig_hup_or_term_handler); | |
308 | |
309 switch (sig) | |
310 { | |
311 #if defined (SIGHUP) | |
312 case SIGHUP: | |
313 { | |
314 if (Vsighup_dumps_octave_core) | |
4791 | 315 dump_octave_core (); |
4449 | 316 } |
317 break; | |
318 #endif | |
319 | |
320 #if defined (SIGTERM) | |
321 case SIGTERM: | |
322 { | |
323 if (Vsigterm_dumps_octave_core) | |
4791 | 324 dump_octave_core (); |
4449 | 325 } |
326 break; | |
327 #endif | |
328 | |
329 default: | |
330 break; | |
331 } | |
332 | |
333 clean_up_and_exit (0); | |
334 | |
335 SIGHANDLER_RETURN (0); | |
336 } | |
337 #endif | |
338 | |
3343 | 339 #if 0 |
3281 | 340 #if defined (SIGWINCH) |
341 static RETSIGTYPE | |
342 sigwinch_handler (int /* sig */) | |
343 { | |
344 MAYBE_ACK_SIGNAL (SIGWINCH); | |
345 | |
346 MAYBE_REINSTALL_SIGHANDLER (SIGWINCH, sigwinch_handler); | |
347 | |
348 command_editor::resize_terminal (); | |
349 | |
350 SIGHANDLER_RETURN (0); | |
351 } | |
352 #endif | |
3343 | 353 #endif |
3281 | 354 |
635 | 355 // Handle SIGINT by restarting the parser (see octave.cc). |
2554 | 356 // |
357 // This also has to work for SIGBREAK (on systems that have it), so we | |
358 // use the value of sig, instead of just assuming that it is called | |
359 // for SIGINT only. | |
635 | 360 |
8658
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
361 static void |
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
362 user_abort (const char *sig_name, int sig_number) |
1 | 363 { |
4172 | 364 if (! octave_initialized) |
365 exit (1); | |
366 | |
1 | 367 if (can_interrupt) |
368 { | |
4185 | 369 if (Vdebug_on_interrupt) |
370 { | |
371 if (! octave_debug_on_interrupt_state) | |
372 { | |
8658
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
373 tree_evaluator::debug_mode = true; |
4185 | 374 octave_debug_on_interrupt_state = true; |
375 | |
5451 | 376 return; |
4185 | 377 } |
378 else | |
8658
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
379 { |
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
380 // Clear the flag and do normal interrupt stuff. |
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
381 |
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
382 tree_evaluator::debug_mode = bp_table::have_breakpoints (); |
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
383 octave_debug_on_interrupt_state = false; |
73c4516fae10
New evaluator and debugger derived from tree-walker class
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
384 } |
4185 | 385 } |
386 | |
4153 | 387 if (octave_interrupt_immediately) |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
388 { |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
389 if (octave_interrupt_state == 0) |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
390 octave_interrupt_state = 1; |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
391 |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
392 octave_jump_to_enclosing_context (); |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
393 } |
4429 | 394 else |
4787 | 395 { |
4793 | 396 // If we are already cleaning up from a previous interrupt, |
397 // take note of the fact that another interrupt signal has | |
398 // arrived. | |
399 | |
400 if (octave_interrupt_state < 0) | |
401 octave_interrupt_state = 0; | |
402 | |
5142 | 403 octave_signal_caught = 1; |
4787 | 404 octave_interrupt_state++; |
405 | |
4791 | 406 if (interactive && octave_interrupt_state == 2) |
407 std::cerr << "Press Control-C again to abort." << std::endl; | |
4787 | 408 |
4791 | 409 if (octave_interrupt_state >= 3) |
5451 | 410 my_friendly_exit (sig_name, sig_number, true); |
4787 | 411 } |
1 | 412 } |
413 | |
5451 | 414 } |
415 | |
416 static RETSIGTYPE | |
417 sigint_handler (int sig) | |
418 { | |
419 MAYBE_ACK_SIGNAL (sig); | |
420 | |
421 MAYBE_REINSTALL_SIGHANDLER (sig, sigint_handler); | |
422 | |
423 #ifdef USE_W32_SIGINT | |
424 if (w32_in_main_thread ()) | |
5844 | 425 user_abort (strsignal (sig), sig); |
5451 | 426 else |
427 w32_raise (sig); | |
428 #else | |
5844 | 429 user_abort (strsignal (sig), sig); |
5451 | 430 #endif |
431 | |
2469 | 432 SIGHANDLER_RETURN (0); |
1 | 433 } |
434 | |
4064 | 435 #ifdef SIGPIPE |
1 | 436 static RETSIGTYPE |
1488 | 437 sigpipe_handler (int /* sig */) |
1 | 438 { |
2626 | 439 MAYBE_ACK_SIGNAL (SIGPIPE); |
2554 | 440 |
441 MAYBE_REINSTALL_SIGHANDLER (SIGPIPE, sigpipe_handler); | |
834 | 442 |
5142 | 443 octave_signal_caught = 1; |
444 | |
445 octave_signals_caught[SIGPIPE] = true; | |
1 | 446 |
1358 | 447 // Don't loop forever on account of this. |
448 | |
5142 | 449 if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0) |
4787 | 450 octave_interrupt_state++; |
1 | 451 |
2469 | 452 SIGHANDLER_RETURN (0); |
1 | 453 } |
4064 | 454 #endif /* defined(SIGPIPE) */ |
1 | 455 |
5451 | 456 #ifdef USE_W32_SIGINT |
457 static BOOL CALLBACK | |
458 w32_sigint_handler (DWORD sig) | |
459 { | |
460 const char *sig_name; | |
461 | |
462 switch(sig) | |
463 { | |
464 case CTRL_BREAK_EVENT: | |
465 sig_name = "Ctrl-Break"; | |
466 break; | |
467 case CTRL_C_EVENT: | |
468 sig_name = "Ctrl-C"; | |
469 break; | |
470 case CTRL_CLOSE_EVENT: | |
471 sig_name = "close console"; | |
472 break; | |
473 case CTRL_LOGOFF_EVENT: | |
474 sig_name = "logoff"; | |
475 break; | |
476 case CTRL_SHUTDOWN_EVENT: | |
477 sig_name = "shutdown"; | |
478 break; | |
479 default: | |
480 sig_name = "unknown console event"; | |
481 break; | |
482 } | |
483 | |
484 switch(sig) | |
485 { | |
486 case CTRL_BREAK_EVENT: | |
487 case CTRL_C_EVENT: | |
488 w32_raise (SIGINT); | |
489 break; | |
490 | |
491 case CTRL_CLOSE_EVENT: | |
492 case CTRL_LOGOFF_EVENT: | |
493 case CTRL_SHUTDOWN_EVENT: | |
494 default: | |
495 // We should do the following: | |
496 // clean_up_and_exit (0); | |
497 // We can't because we aren't running in the normal Octave thread. | |
498 user_abort(sig_name, sig); | |
499 break; | |
500 } | |
501 | |
502 // Return TRUE if the event was handled, or FALSE if another handler | |
503 // should be called. | |
5775 | 504 // FIXME check that windows terminates the thread. |
5451 | 505 return TRUE; |
506 } | |
507 #endif /* w32_sigint_handler */ | |
508 | |
509 | |
2705 | 510 octave_interrupt_handler |
2554 | 511 octave_catch_interrupts (void) |
512 { | |
2705 | 513 octave_interrupt_handler retval; |
2554 | 514 |
515 #ifdef SIGINT | |
2705 | 516 retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler); |
2554 | 517 #endif |
518 | |
519 #ifdef SIGBREAK | |
2705 | 520 retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler); |
2554 | 521 #endif |
2705 | 522 |
5451 | 523 #ifdef USE_W32_SIGINT |
524 | |
525 // Intercept windows console control events. | |
526 // Note that the windows console signal handlers chain, so if | |
527 // install_signal_handlers is called more than once in the same program, | |
528 // then first call the following to avoid duplicates: | |
529 // | |
530 // SetConsoleCtrlHandler (w32_sigint_handler, FALSE); | |
531 | |
532 if (! SetConsoleCtrlHandler (w32_sigint_handler, TRUE)) | |
533 error ("SetConsoleCtrlHandler failed with %ld\n", GetLastError ()); | |
534 | |
535 w32_set_quiet_shutdown (); | |
536 | |
537 #endif | |
538 | |
2705 | 539 return retval; |
2554 | 540 } |
541 | |
2705 | 542 octave_interrupt_handler |
543 octave_ignore_interrupts (void) | |
2554 | 544 { |
2705 | 545 octave_interrupt_handler retval; |
546 | |
2554 | 547 #ifdef SIGINT |
2705 | 548 retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN); |
2554 | 549 #endif |
550 | |
551 #ifdef SIGBREAK | |
2705 | 552 retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN); |
2554 | 553 #endif |
2705 | 554 |
555 return retval; | |
556 } | |
557 | |
558 octave_interrupt_handler | |
5770 | 559 octave_set_interrupt_handler (const volatile octave_interrupt_handler& h, |
560 bool restart_syscalls) | |
2705 | 561 { |
562 octave_interrupt_handler retval; | |
563 | |
564 #ifdef SIGINT | |
5770 | 565 retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler, |
566 restart_syscalls); | |
2705 | 567 #endif |
568 | |
569 #ifdef SIGBREAK | |
5770 | 570 retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler, |
571 restart_syscalls); | |
2705 | 572 #endif |
573 | |
574 return retval; | |
1651 | 575 } |
576 | |
635 | 577 // Install all the handlers for the signals we might care about. |
578 | |
1 | 579 void |
580 install_signal_handlers (void) | |
581 { | |
5142 | 582 for (int i = 0; i < NSIG; i++) |
583 octave_signals_caught[i] = false; | |
584 | |
2554 | 585 octave_catch_interrupts (); |
586 | |
1 | 587 #ifdef SIGABRT |
1446 | 588 octave_set_signal_handler (SIGABRT, generic_sig_handler); |
1 | 589 #endif |
590 | |
591 #ifdef SIGALRM | |
1446 | 592 octave_set_signal_handler (SIGALRM, generic_sig_handler); |
1 | 593 #endif |
594 | |
595 #ifdef SIGBUS | |
1446 | 596 octave_set_signal_handler (SIGBUS, generic_sig_handler); |
1 | 597 #endif |
598 | |
1230 | 599 #ifdef SIGCHLD |
1446 | 600 octave_set_signal_handler (SIGCHLD, sigchld_handler); |
1230 | 601 #endif |
602 | |
3174 | 603 // SIGCLD |
604 // SIGCONT | |
605 | |
1 | 606 #ifdef SIGEMT |
1446 | 607 octave_set_signal_handler (SIGEMT, generic_sig_handler); |
1 | 608 #endif |
609 | |
610 #ifdef SIGFPE | |
1373 | 611 #if defined (__alpha__) |
1446 | 612 octave_set_signal_handler (SIGFPE, sigfpe_handler); |
1373 | 613 #else |
1446 | 614 octave_set_signal_handler (SIGFPE, generic_sig_handler); |
1 | 615 #endif |
1373 | 616 #endif |
1 | 617 |
618 #ifdef SIGHUP | |
4449 | 619 octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler); |
1 | 620 #endif |
621 | |
622 #ifdef SIGILL | |
1446 | 623 octave_set_signal_handler (SIGILL, generic_sig_handler); |
1 | 624 #endif |
625 | |
3174 | 626 // SIGINFO |
627 // SIGINT | |
628 | |
1 | 629 #ifdef SIGIOT |
1446 | 630 octave_set_signal_handler (SIGIOT, generic_sig_handler); |
1 | 631 #endif |
632 | |
633 #ifdef SIGLOST | |
1446 | 634 octave_set_signal_handler (SIGLOST, generic_sig_handler); |
1 | 635 #endif |
636 | |
637 #ifdef SIGPIPE | |
1446 | 638 octave_set_signal_handler (SIGPIPE, sigpipe_handler); |
1 | 639 #endif |
640 | |
641 #ifdef SIGPOLL | |
1446 | 642 octave_set_signal_handler (SIGPOLL, SIG_IGN); |
1 | 643 #endif |
644 | |
5866 | 645 // SIGPROF |
3174 | 646 // SIGPWR |
647 | |
1 | 648 #ifdef SIGQUIT |
1446 | 649 octave_set_signal_handler (SIGQUIT, generic_sig_handler); |
1 | 650 #endif |
651 | |
652 #ifdef SIGSEGV | |
1446 | 653 octave_set_signal_handler (SIGSEGV, generic_sig_handler); |
1 | 654 #endif |
655 | |
3174 | 656 // SIGSTOP |
657 | |
1 | 658 #ifdef SIGSYS |
1446 | 659 octave_set_signal_handler (SIGSYS, generic_sig_handler); |
1 | 660 #endif |
661 | |
662 #ifdef SIGTERM | |
4449 | 663 octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler); |
1 | 664 #endif |
665 | |
666 #ifdef SIGTRAP | |
1446 | 667 octave_set_signal_handler (SIGTRAP, generic_sig_handler); |
1 | 668 #endif |
669 | |
3174 | 670 // SIGTSTP |
671 // SIGTTIN | |
672 // SIGTTOU | |
673 // SIGURG | |
674 | |
1 | 675 #ifdef SIGUSR1 |
1446 | 676 octave_set_signal_handler (SIGUSR1, generic_sig_handler); |
1 | 677 #endif |
678 | |
679 #ifdef SIGUSR2 | |
1446 | 680 octave_set_signal_handler (SIGUSR2, generic_sig_handler); |
1 | 681 #endif |
682 | |
683 #ifdef SIGVTALRM | |
1446 | 684 octave_set_signal_handler (SIGVTALRM, generic_sig_handler); |
1 | 685 #endif |
686 | |
895 | 687 #ifdef SIGIO |
1446 | 688 octave_set_signal_handler (SIGIO, SIG_IGN); |
895 | 689 #endif |
690 | |
3343 | 691 #if 0 |
3281 | 692 #ifdef SIGWINCH |
693 octave_set_signal_handler (SIGWINCH, sigwinch_handler); | |
694 #endif | |
3343 | 695 #endif |
3174 | 696 |
1 | 697 #ifdef SIGXCPU |
1446 | 698 octave_set_signal_handler (SIGXCPU, generic_sig_handler); |
1 | 699 #endif |
700 | |
701 #ifdef SIGXFSZ | |
1446 | 702 octave_set_signal_handler (SIGXFSZ, generic_sig_handler); |
1 | 703 #endif |
5451 | 704 |
1 | 705 } |
706 | |
4294 | 707 static Octave_map |
708 make_sig_struct (void) | |
709 { | |
710 Octave_map m; | |
711 | |
712 #ifdef SIGABRT | |
4675 | 713 m.assign ("ABRT", SIGABRT); |
4294 | 714 #endif |
715 | |
716 #ifdef SIGALRM | |
4675 | 717 m.assign ("ALRM", SIGALRM); |
4294 | 718 #endif |
719 | |
720 #ifdef SIGBUS | |
4675 | 721 m.assign ("BUS", SIGBUS); |
4294 | 722 #endif |
723 | |
724 #ifdef SIGCHLD | |
4675 | 725 m.assign ("CHLD", SIGCHLD); |
4294 | 726 #endif |
727 | |
728 #ifdef SIGCLD | |
4675 | 729 m.assign ("CLD", SIGCLD); |
4294 | 730 #endif |
731 | |
732 #ifdef SIGCONT | |
4675 | 733 m.assign ("CONT", SIGCONT); |
4294 | 734 #endif |
735 | |
736 #ifdef SIGEMT | |
4675 | 737 m.assign ("EMT", SIGEMT); |
4294 | 738 #endif |
739 | |
740 #ifdef SIGFPE | |
4675 | 741 m.assign ("FPE", SIGFPE); |
4294 | 742 #endif |
743 | |
744 #ifdef SIGHUP | |
4675 | 745 m.assign ("HUP", SIGHUP); |
4294 | 746 #endif |
747 | |
748 #ifdef SIGILL | |
4675 | 749 m.assign ("ILL", SIGILL); |
4294 | 750 #endif |
751 | |
752 #ifdef SIGINFO | |
4675 | 753 m.assign ("INFO", SIGINFO); |
4294 | 754 #endif |
755 | |
756 #ifdef SIGINT | |
4675 | 757 m.assign ("INT", SIGINT); |
4294 | 758 #endif |
759 | |
760 #ifdef SIGIOT | |
4675 | 761 m.assign ("IOT", SIGIOT); |
4294 | 762 #endif |
763 | |
764 #ifdef SIGLOST | |
4675 | 765 m.assign ("LOST", SIGLOST); |
4294 | 766 #endif |
767 | |
768 #ifdef SIGPIPE | |
4675 | 769 m.assign ("PIPE", SIGPIPE); |
4294 | 770 #endif |
771 | |
772 #ifdef SIGPOLL | |
4675 | 773 m.assign ("POLL", SIGPOLL); |
4294 | 774 #endif |
775 | |
776 #ifdef SIGPROF | |
4675 | 777 m.assign ("PROF", SIGPROF); |
4294 | 778 #endif |
779 | |
780 #ifdef SIGPWR | |
4675 | 781 m.assign ("PWR", SIGPWR); |
4294 | 782 #endif |
783 | |
784 #ifdef SIGQUIT | |
4675 | 785 m.assign ("QUIT", SIGQUIT); |
4294 | 786 #endif |
787 | |
788 #ifdef SIGSEGV | |
4675 | 789 m.assign ("SEGV", SIGSEGV); |
4294 | 790 #endif |
791 | |
792 #ifdef SIGSTOP | |
4675 | 793 m.assign ("STOP", SIGSTOP); |
4294 | 794 #endif |
795 | |
796 #ifdef SIGSYS | |
4675 | 797 m.assign ("SYS", SIGSYS); |
4294 | 798 #endif |
799 | |
800 #ifdef SIGTERM | |
4675 | 801 m.assign ("TERM", SIGTERM); |
4294 | 802 #endif |
803 | |
804 #ifdef SIGTRAP | |
4675 | 805 m.assign ("TRAP", SIGTRAP); |
4294 | 806 #endif |
807 | |
808 #ifdef SIGTSTP | |
4675 | 809 m.assign ("TSTP", SIGTSTP); |
4294 | 810 #endif |
811 | |
812 #ifdef SIGTTIN | |
4675 | 813 m.assign ("TTIN", SIGTTIN); |
4294 | 814 #endif |
815 | |
816 #ifdef SIGTTOU | |
4675 | 817 m.assign ("TTOU", SIGTTOU); |
4294 | 818 #endif |
819 | |
820 #ifdef SIGURG | |
4675 | 821 m.assign ("URG", SIGURG); |
4294 | 822 #endif |
823 | |
824 #ifdef SIGUSR1 | |
4675 | 825 m.assign ("USR1", SIGUSR1); |
4294 | 826 #endif |
827 | |
828 #ifdef SIGUSR2 | |
4675 | 829 m.assign ("USR2", SIGUSR2); |
4294 | 830 #endif |
831 | |
832 #ifdef SIGVTALRM | |
4675 | 833 m.assign ("VTALRM", SIGVTALRM); |
4294 | 834 #endif |
835 | |
836 #ifdef SIGIO | |
4675 | 837 m.assign ("IO", SIGIO); |
4294 | 838 #endif |
839 | |
840 #ifdef SIGWINCH | |
4675 | 841 m.assign ("WINCH", SIGWINCH); |
4294 | 842 #endif |
843 | |
844 #ifdef SIGXCPU | |
4675 | 845 m.assign ("XCPU", SIGXCPU); |
4294 | 846 #endif |
847 | |
848 #ifdef SIGXFSZ | |
4675 | 849 m.assign ("XFSZ", SIGXFSZ); |
4294 | 850 #endif |
851 | |
852 return m; | |
853 } | |
854 | |
5142 | 855 octave_child_list::octave_child_list_rep *octave_child_list::instance = 0; |
5128 | 856 |
2926 | 857 bool |
858 octave_child_list::instance_ok (void) | |
859 { | |
860 bool retval = true; | |
861 | |
862 if (! instance) | |
5142 | 863 instance = new octave_child_list_rep (); |
2926 | 864 |
865 if (! instance) | |
866 { | |
867 ::error ("unable to create child list object!"); | |
868 | |
869 retval = false; | |
870 } | |
871 | |
872 return retval; | |
873 } | |
874 | |
875 void | |
5142 | 876 octave_child_list::insert (pid_t pid, octave_child::child_event_handler f) |
877 { | |
878 if (instance_ok ()) | |
879 instance->insert (pid, f); | |
880 } | |
881 | |
882 void | |
883 octave_child_list::reap (void) | |
2926 | 884 { |
885 if (instance_ok ()) | |
5142 | 886 instance->reap (); |
887 } | |
888 | |
889 bool | |
890 octave_child_list::wait (void) | |
891 { | |
892 return (instance_ok ()) ? instance->wait () : false; | |
2926 | 893 } |
894 | |
5142 | 895 class pid_equal |
896 { | |
897 public: | |
898 | |
899 pid_equal (pid_t v) : val (v) { } | |
900 | |
901 bool operator () (const octave_child& oc) const { return oc.pid == val; } | |
902 | |
903 private: | |
904 | |
905 pid_t val; | |
906 }; | |
907 | |
2926 | 908 void |
909 octave_child_list::remove (pid_t pid) | |
910 { | |
911 if (instance_ok ()) | |
5142 | 912 instance->remove_if (pid_equal (pid)); |
2926 | 913 } |
914 | |
5142 | 915 #define OCL_REP octave_child_list::octave_child_list_rep |
2926 | 916 |
5142 | 917 void |
918 OCL_REP::insert (pid_t pid, octave_child::child_event_handler f) | |
2926 | 919 { |
5142 | 920 append (octave_child (pid, f)); |
2926 | 921 } |
922 | |
2209 | 923 void |
5142 | 924 OCL_REP::reap (void) |
2209 | 925 { |
5142 | 926 // Mark the record for PID invalid. |
2209 | 927 |
5142 | 928 for (iterator p = begin (); p != end (); p++) |
929 { | |
930 // The call to the octave_child::child_event_handler might | |
931 // invalidate the iterator (for example, by calling | |
932 // octave_child_list::remove), so we increment the iterator | |
933 // here. | |
2209 | 934 |
5142 | 935 octave_child& oc = *p; |
2209 | 936 |
5142 | 937 if (oc.have_status) |
2209 | 938 { |
5142 | 939 oc.have_status = 0; |
940 | |
941 octave_child::child_event_handler f = oc.handler; | |
942 | |
943 if (f && f (oc.pid, oc.status)) | |
944 oc.pid = -1; | |
2209 | 945 } |
946 } | |
947 | |
5142 | 948 remove_if (pid_equal (-1)); |
2209 | 949 } |
950 | |
5142 | 951 // Wait on our children and record any changes in their status. |
952 | |
953 bool | |
954 OCL_REP::wait (void) | |
2210 | 955 { |
5142 | 956 bool retval = false; |
2210 | 957 |
5142 | 958 for (iterator p = begin (); p != end (); p++) |
2210 | 959 { |
5142 | 960 octave_child& oc = *p; |
961 | |
962 pid_t pid = oc.pid; | |
963 | |
964 if (pid > 0) | |
965 { | |
966 int status; | |
2210 | 967 |
5453 | 968 if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0) |
5142 | 969 { |
970 oc.have_status = 1; | |
971 | |
972 oc.status = status; | |
973 | |
974 retval = true; | |
975 | |
976 break; | |
977 } | |
2210 | 978 } |
979 } | |
980 | |
5142 | 981 return retval; |
2210 | 982 } |
983 | |
5780 | 984 DEFUN (SIG, args, , |
985 "-*- texinfo -*-\n\ | |
986 @deftypefn {Built-in Function} {} SIG ()\n\ | |
987 Return a structure containing Unix signal names and their defined values.\n\ | |
988 @end deftypefn") | |
989 { | |
990 octave_value retval; | |
991 | |
992 if (args.length () == 0) | |
993 { | |
994 static Octave_map m = make_sig_struct (); | |
995 | |
996 retval = m; | |
997 } | |
998 else | |
5823 | 999 print_usage (); |
5780 | 1000 |
1001 return retval; | |
1002 } | |
1003 | |
5794 | 1004 DEFUN (debug_on_interrupt, args, nargout, |
1005 "-*- texinfo -*-\n\ | |
1006 @deftypefn {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\ | |
1007 @deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\ | |
1008 Query or set the internal variable that controls whether Octave will try\n\ | |
1009 to enter debugging mode when it receives an interrupt signal (typically\n\ | |
1010 generated with @kbd{C-c}). If a second interrupt signal is received\n\ | |
1011 before reaching the debugging mode, a normal interrupt will occur.\n\ | |
1012 @end deftypefn") | |
4449 | 1013 { |
5794 | 1014 return SET_INTERNAL_VARIABLE (debug_on_interrupt); |
4449 | 1015 } |
1016 | |
5794 | 1017 DEFUN (sighup_dumps_octave_core, args, nargout, |
1018 "-*- texinfo -*-\n\ | |
1019 @deftypefn {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\ | |
1020 @deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\ | |
1021 Query or set the internal variable that controls whether Octave tries\n\ | |
6653 | 1022 to save all current variables to the file \"octave-core\" if it receives\n\ |
5794 | 1023 a hangup signal.\n\ |
1024 @end deftypefn") | |
4185 | 1025 { |
5794 | 1026 return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core); |
1027 } | |
4294 | 1028 |
5794 | 1029 DEFUN (sigterm_dumps_octave_core, args, nargout, |
1030 "-*- texinfo -*-\n\ | |
1031 @deftypefn {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\ | |
1032 @deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\ | |
1033 Query or set the internal variable that controls whether Octave tries\n\ | |
6653 | 1034 to save all current variables to the file \"octave-core\" if it receives\n\ |
5794 | 1035 a terminate signal.\n\ |
1036 @end deftypefn") | |
1037 { | |
1038 return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core); | |
4185 | 1039 } |
1040 | |
1 | 1041 /* |
1042 ;;; Local Variables: *** | |
1043 ;;; mode: C++ *** | |
1044 ;;; End: *** | |
1045 */ |