sighandlers.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1993-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <cstdlib>
00028 
00029 #include <iostream>
00030 #include <new>
00031 
00032 #include <sys/types.h>
00033 #include <unistd.h>
00034 
00035 #include "cmd-edit.h"
00036 #include "oct-syscalls.h"
00037 #include "quit.h"
00038 #include "singleton-cleanup.h"
00039 
00040 #include "debug.h"
00041 #include "defun.h"
00042 #include "error.h"
00043 #include "input.h"
00044 #include "load-save.h"
00045 #include "oct-map.h"
00046 #include "pager.h"
00047 #include "pt-bp.h"
00048 #include "pt-eval.h"
00049 #include "sighandlers.h"
00050 #include "sysdep.h"
00051 #include "syswait.h"
00052 #include "toplev.h"
00053 #include "utils.h"
00054 #include "variables.h"
00055 
00056 // Nonzero means we have already printed a message for this series of
00057 // SIGPIPES.  We assume that the writer will eventually give up.
00058 int pipe_handler_error_count = 0;
00059 
00060 // TRUE means we can be interrupted.
00061 bool can_interrupt = false;
00062 
00063 // TRUE means we should try to enter the debugger on SIGINT.
00064 static bool Vdebug_on_interrupt = false;
00065 
00066 // Allow users to avoid writing octave-core for SIGHUP (sent by
00067 // closing gnome-terminal, for example).  Note that this variable has
00068 // no effect if Vcrash_dumps_octave_core is FALSE.
00069 static bool Vsighup_dumps_octave_core = true;
00070 
00071 // Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
00072 static bool Vsigterm_dumps_octave_core = true;
00073 
00074 // List of signals we have caught since last call to octave_signal_handler.
00075 static bool octave_signals_caught[NSIG];
00076 
00077 // Signal handler return type.
00078 #ifndef BADSIG
00079 #define BADSIG (void (*)(int))-1
00080 #endif
00081 
00082 // The following is a workaround for an apparent bug in GCC 4.1.2 and
00083 // possibly earlier versions.  See Octave bug report #30685 for details.
00084 #if defined (__GNUC__)
00085 # if ! (__GNUC__ > 4 \
00086         || (__GNUC__ == 4 && (__GNUC_MINOR__ > 1 \
00087                               || (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ > 2))))
00088 #  undef GNULIB_NAMESPACE
00089 #  define GNULIB_NAMESPACE
00090 #  warning "disabling GNULIB_NAMESPACE for signal functions -- consider upgrading to a current version of GCC"
00091 # endif
00092 #endif
00093 
00094 #define BLOCK_SIGNAL(sig, nvar, ovar) \
00095   do \
00096     { \
00097       GNULIB_NAMESPACE::sigemptyset (&nvar); \
00098       GNULIB_NAMESPACE::sigaddset (&nvar, sig); \
00099       GNULIB_NAMESPACE::sigemptyset (&ovar); \
00100       GNULIB_NAMESPACE::sigprocmask (SIG_BLOCK, &nvar, &ovar); \
00101     } \
00102   while (0)
00103 
00104 #if !defined (SIGCHLD) && defined (SIGCLD)
00105 #define SIGCHLD SIGCLD
00106 #endif
00107 
00108 #define BLOCK_CHILD(nvar, ovar) BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
00109 #define UNBLOCK_CHILD(ovar) GNULIB_NAMESPACE::sigprocmask (SIG_SETMASK, &ovar, 0)
00110 
00111 // Called from octave_quit () to actually do something about the signals
00112 // we have caught.
00113 
00114 void
00115 octave_signal_handler (void)
00116 {
00117   // The list of signals is relatively short, so we will just go
00118   // linearly through the list.
00119 
00120   for (int i = 0; i < NSIG; i++)
00121     {
00122       if (octave_signals_caught[i])
00123         {
00124           octave_signals_caught[i] = false;
00125 
00126           switch (i)
00127             {
00128 #ifdef SIGCHLD
00129             case SIGCHLD:
00130               {
00131                 volatile octave_interrupt_handler saved_interrupt_handler
00132                   = octave_ignore_interrupts ();
00133 
00134                 sigset_t set, oset;
00135 
00136                 BLOCK_CHILD (set, oset);
00137 
00138                 octave_child_list::wait ();
00139 
00140                 octave_set_interrupt_handler (saved_interrupt_handler);
00141 
00142                 UNBLOCK_CHILD (oset);
00143 
00144                 octave_child_list::reap ();
00145               }
00146               break;
00147 #endif
00148 
00149             case SIGFPE:
00150               std::cerr << "warning: floating point exception -- trying to return to prompt" << std::endl;
00151               break;
00152 
00153 #ifdef SIGPIPE
00154             case SIGPIPE:
00155               std::cerr << "warning: broken pipe -- some output may be lost" << std::endl;
00156               break;
00157 #endif
00158             }
00159         }
00160     }
00161 }
00162 
00163 static void
00164 my_friendly_exit (const char *sig_name, int sig_number,
00165                   bool save_vars = true)
00166 {
00167   static bool been_there_done_that = false;
00168 
00169   if (been_there_done_that)
00170     {
00171 #if defined (SIGABRT)
00172       octave_set_signal_handler (SIGABRT, SIG_DFL);
00173 #endif
00174 
00175       std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";
00176 
00177       MINGW_SIGNAL_CLEANUP ();
00178 
00179       abort ();
00180     }
00181   else
00182     {
00183       been_there_done_that = true;
00184 
00185       std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
00186 
00187       if (save_vars)
00188         dump_octave_core ();
00189 
00190       if (sig_number < 0)
00191         {
00192           MINGW_SIGNAL_CLEANUP ();
00193 
00194           exit (1);
00195         }
00196       else
00197         {
00198           octave_set_signal_handler (sig_number, SIG_DFL);
00199 
00200           GNULIB_NAMESPACE::raise (sig_number);
00201         }
00202     }
00203 }
00204 
00205 sig_handler *
00206 octave_set_signal_handler (int sig, sig_handler *handler,
00207                            bool restart_syscalls)
00208 {
00209   struct sigaction act, oact;
00210 
00211   act.sa_handler = handler;
00212   act.sa_flags = 0;
00213 
00214 #if defined (SIGALRM)
00215   if (sig == SIGALRM)
00216     {
00217 #if defined (SA_INTERRUPT)
00218       act.sa_flags |= SA_INTERRUPT;
00219 #endif
00220     }
00221 #endif
00222 #if defined (SA_RESTART)
00223 #if defined (SIGALRM)
00224   else
00225 #endif
00226   // FIXME -- Do we also need to explicitly disable SA_RESTART?
00227   if (restart_syscalls)
00228     act.sa_flags |= SA_RESTART;
00229 #endif
00230 
00231   GNULIB_NAMESPACE::sigemptyset (&act.sa_mask);
00232   GNULIB_NAMESPACE::sigemptyset (&oact.sa_mask);
00233 
00234   GNULIB_NAMESPACE::sigaction (sig, &act, &oact);
00235 
00236   return oact.sa_handler;
00237 }
00238 
00239 static void
00240 generic_sig_handler (int sig)
00241 {
00242   my_friendly_exit (strsignal (sig), sig);
00243 }
00244 
00245 // Handle SIGCHLD.
00246 
00247 #ifdef SIGCHLD
00248 static void
00249 sigchld_handler (int /* sig */)
00250 {
00251   octave_signal_caught = 1;
00252 
00253   octave_signals_caught[SIGCHLD] = true;
00254 }
00255 #endif /* defined(SIGCHLD) */
00256 
00257 #ifdef SIGFPE
00258 #if defined (__alpha__)
00259 static void
00260 sigfpe_handler (int /* sig */)
00261 {
00262   if (can_interrupt && octave_interrupt_state >= 0)
00263     {
00264       octave_signal_caught = 1;
00265 
00266       octave_signals_caught[SIGFPE] = true;
00267 
00268       octave_interrupt_state++;
00269     }
00270 }
00271 #endif /* defined(__alpha__) */
00272 #endif /* defined(SIGFPE) */
00273 
00274 #if defined (SIGHUP) || defined (SIGTERM)
00275 static void
00276 sig_hup_or_term_handler (int sig)
00277 {
00278   switch (sig)
00279     {
00280 #if defined (SIGHUP)
00281     case SIGHUP:
00282       {
00283         if (Vsighup_dumps_octave_core)
00284           dump_octave_core ();
00285       }
00286       break;
00287 #endif
00288 
00289 #if defined (SIGTERM)
00290     case SIGTERM:
00291       {
00292         if (Vsigterm_dumps_octave_core)
00293           dump_octave_core ();
00294       }
00295       break;
00296 #endif
00297 
00298     default:
00299       break;
00300     }
00301 
00302   clean_up_and_exit (0);
00303 }
00304 #endif
00305 
00306 #if 0
00307 #if defined (SIGWINCH)
00308 static void
00309 sigwinch_handler (int /* sig */)
00310 {
00311   command_editor::resize_terminal ();
00312 }
00313 #endif
00314 #endif
00315 
00316 // Handle SIGINT by restarting the parser (see octave.cc).
00317 //
00318 // This also has to work for SIGBREAK (on systems that have it), so we
00319 // use the value of sig, instead of just assuming that it is called
00320 // for SIGINT only.
00321 
00322 static void
00323 user_abort (const char *sig_name, int sig_number)
00324 {
00325   if (! octave_initialized)
00326     exit (1);
00327 
00328   if (can_interrupt)
00329     {
00330       if (Vdebug_on_interrupt)
00331         {
00332           if (! octave_debug_on_interrupt_state)
00333             {
00334               tree_evaluator::debug_mode = true;
00335               octave_debug_on_interrupt_state = true;
00336 
00337               return;
00338             }
00339           else
00340             {
00341               // Clear the flag and do normal interrupt stuff.
00342 
00343               tree_evaluator::debug_mode
00344                 = bp_table::have_breakpoints () || Vdebugging;
00345               octave_debug_on_interrupt_state = false;
00346             }
00347         }
00348 
00349       if (octave_interrupt_immediately)
00350         {
00351           if (octave_interrupt_state == 0)
00352             octave_interrupt_state = 1;
00353 
00354           octave_jump_to_enclosing_context ();
00355         }
00356       else
00357         {
00358           // If we are already cleaning up from a previous interrupt,
00359           // take note of the fact that another interrupt signal has
00360           // arrived.
00361 
00362           if (octave_interrupt_state < 0)
00363             octave_interrupt_state = 0;
00364 
00365           octave_signal_caught = 1;
00366           octave_interrupt_state++;
00367 
00368           if (interactive && octave_interrupt_state == 2)
00369             std::cerr << "Press Control-C again to abort." << std::endl;
00370 
00371           if (octave_interrupt_state >= 3)
00372             my_friendly_exit (sig_name, sig_number, true);
00373         }
00374     }
00375 
00376 }
00377 
00378 static void
00379 sigint_handler (int sig)
00380 {
00381 #ifdef USE_W32_SIGINT
00382   if (w32_in_main_thread ())
00383     user_abort (strsignal (sig), sig);
00384   else
00385     w32_raise (sig);
00386 #else
00387   user_abort (strsignal (sig), sig);
00388 #endif
00389 }
00390 
00391 #ifdef SIGPIPE
00392 static void
00393 sigpipe_handler (int /* sig */)
00394 {
00395   octave_signal_caught = 1;
00396 
00397   octave_signals_caught[SIGPIPE] = true;
00398 
00399   // Don't loop forever on account of this.
00400 
00401   if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
00402     octave_interrupt_state++;
00403 }
00404 #endif /* defined(SIGPIPE) */
00405 
00406 #ifdef USE_W32_SIGINT
00407 static BOOL CALLBACK
00408 w32_sigint_handler (DWORD sig)
00409 {
00410   const char *sig_name;
00411 
00412   switch(sig)
00413     {
00414       case CTRL_BREAK_EVENT:
00415         sig_name = "Ctrl-Break";
00416         break;
00417       case CTRL_C_EVENT:
00418         sig_name = "Ctrl-C";
00419         break;
00420       case CTRL_CLOSE_EVENT:
00421         sig_name = "close console";
00422         break;
00423       case CTRL_LOGOFF_EVENT:
00424         sig_name = "logoff";
00425         break;
00426       case CTRL_SHUTDOWN_EVENT:
00427         sig_name = "shutdown";
00428         break;
00429       default:
00430         sig_name = "unknown console event";
00431         break;
00432     }
00433 
00434   switch(sig)
00435     {
00436       case CTRL_BREAK_EVENT:
00437       case CTRL_C_EVENT:
00438         w32_raise (SIGINT);
00439         break;
00440 
00441       case CTRL_CLOSE_EVENT:
00442       case CTRL_LOGOFF_EVENT:
00443       case CTRL_SHUTDOWN_EVENT:
00444       default:
00445         // We should do the following:
00446         //    clean_up_and_exit (0);
00447         // We can't because we aren't running in the normal Octave thread.
00448         user_abort(sig_name, sig);
00449         break;
00450     }
00451 
00452   // Return TRUE if the event was handled, or FALSE if another handler
00453   // should be called.
00454   // FIXME check that windows terminates the thread.
00455   return TRUE;
00456 }
00457 #endif /* w32_sigint_handler */
00458 
00459 
00460 octave_interrupt_handler
00461 octave_catch_interrupts (void)
00462 {
00463   octave_interrupt_handler retval;
00464 
00465 #ifdef SIGINT
00466   retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
00467 #endif
00468 
00469 #ifdef SIGBREAK
00470   retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
00471 #endif
00472 
00473 #ifdef USE_W32_SIGINT
00474 
00475   // Intercept windows console control events.
00476   // Note that the windows console signal handlers chain, so if
00477   // install_signal_handlers is called more than once in the same program,
00478   // then first call the following to avoid duplicates:
00479   //
00480   //   SetConsoleCtrlHandler (w32_sigint_handler, FALSE);
00481 
00482   if (! SetConsoleCtrlHandler (w32_sigint_handler, TRUE))
00483     error ("SetConsoleCtrlHandler failed with %ld\n", GetLastError ());
00484 
00485   w32_set_quiet_shutdown ();
00486 
00487 #endif
00488 
00489   return retval;
00490 }
00491 
00492 octave_interrupt_handler
00493 octave_ignore_interrupts (void)
00494 {
00495   octave_interrupt_handler retval;
00496 
00497 #ifdef SIGINT
00498   retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
00499 #endif
00500 
00501 #ifdef SIGBREAK
00502   retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
00503 #endif
00504 
00505   return retval;
00506 }
00507 
00508 octave_interrupt_handler
00509 octave_set_interrupt_handler (const volatile octave_interrupt_handler& h,
00510                               bool restart_syscalls)
00511 {
00512   octave_interrupt_handler retval;
00513 
00514 #ifdef SIGINT
00515   retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
00516                                                   restart_syscalls);
00517 #endif
00518 
00519 #ifdef SIGBREAK
00520   retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
00521                                                   restart_syscalls);
00522 #endif
00523 
00524   return retval;
00525 }
00526 
00527 // Install all the handlers for the signals we might care about.
00528 
00529 void
00530 install_signal_handlers (void)
00531 {
00532   for (int i = 0; i < NSIG; i++)
00533     octave_signals_caught[i] = false;
00534 
00535   octave_catch_interrupts ();
00536 
00537 #ifdef SIGABRT
00538   octave_set_signal_handler (SIGABRT, generic_sig_handler);
00539 #endif
00540 
00541 #ifdef SIGALRM
00542   octave_set_signal_handler (SIGALRM, generic_sig_handler);
00543 #endif
00544 
00545 #ifdef SIGBUS
00546   octave_set_signal_handler (SIGBUS, generic_sig_handler);
00547 #endif
00548 
00549 #ifdef SIGCHLD
00550   octave_set_signal_handler (SIGCHLD, sigchld_handler);
00551 #endif
00552 
00553   // SIGCLD
00554   // SIGCONT
00555 
00556 #ifdef SIGEMT
00557   octave_set_signal_handler (SIGEMT, generic_sig_handler);
00558 #endif
00559 
00560 #ifdef SIGFPE
00561 #if defined (__alpha__)
00562   octave_set_signal_handler (SIGFPE, sigfpe_handler);
00563 #else
00564   octave_set_signal_handler (SIGFPE, generic_sig_handler);
00565 #endif
00566 #endif
00567 
00568 #ifdef SIGHUP
00569   octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
00570 #endif
00571 
00572 #ifdef SIGILL
00573   octave_set_signal_handler (SIGILL, generic_sig_handler);
00574 #endif
00575 
00576   // SIGINFO
00577   // SIGINT
00578 
00579 #ifdef SIGIOT
00580   octave_set_signal_handler (SIGIOT, generic_sig_handler);
00581 #endif
00582 
00583 #ifdef SIGLOST
00584   octave_set_signal_handler (SIGLOST, generic_sig_handler);
00585 #endif
00586 
00587 #ifdef SIGPIPE
00588   octave_set_signal_handler (SIGPIPE, sigpipe_handler);
00589 #endif
00590 
00591 #ifdef SIGPOLL
00592   octave_set_signal_handler (SIGPOLL, SIG_IGN);
00593 #endif
00594 
00595   // SIGPROF
00596   // SIGPWR
00597 
00598 #ifdef SIGQUIT
00599   octave_set_signal_handler (SIGQUIT, generic_sig_handler);
00600 #endif
00601 
00602 #ifdef SIGSEGV
00603   octave_set_signal_handler (SIGSEGV, generic_sig_handler);
00604 #endif
00605 
00606   // SIGSTOP
00607 
00608 #ifdef SIGSYS
00609   octave_set_signal_handler (SIGSYS, generic_sig_handler);
00610 #endif
00611 
00612 #ifdef SIGTERM
00613   octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
00614 #endif
00615 
00616 #ifdef SIGTRAP
00617   octave_set_signal_handler (SIGTRAP, generic_sig_handler);
00618 #endif
00619 
00620   // SIGTSTP
00621   // SIGTTIN
00622   // SIGTTOU
00623   // SIGURG
00624 
00625 #ifdef SIGUSR1
00626   octave_set_signal_handler (SIGUSR1, generic_sig_handler);
00627 #endif
00628 
00629 #ifdef SIGUSR2
00630   octave_set_signal_handler (SIGUSR2, generic_sig_handler);
00631 #endif
00632 
00633 #ifdef SIGVTALRM
00634   octave_set_signal_handler (SIGVTALRM, generic_sig_handler);
00635 #endif
00636 
00637 #ifdef SIGIO
00638   octave_set_signal_handler (SIGIO, SIG_IGN);
00639 #endif
00640 
00641 #if 0
00642 #ifdef SIGWINCH
00643   octave_set_signal_handler (SIGWINCH, sigwinch_handler);
00644 #endif
00645 #endif
00646 
00647 #ifdef SIGXCPU
00648   octave_set_signal_handler (SIGXCPU, generic_sig_handler);
00649 #endif
00650 
00651 #ifdef SIGXFSZ
00652   octave_set_signal_handler (SIGXFSZ, generic_sig_handler);
00653 #endif
00654 
00655 }
00656 
00657 static octave_scalar_map
00658 make_sig_struct (void)
00659 {
00660   octave_scalar_map m;
00661 
00662 #ifdef SIGABRT
00663   m.assign ("ABRT", SIGABRT);
00664 #endif
00665 
00666 #ifdef SIGALRM
00667   m.assign ("ALRM", SIGALRM);
00668 #endif
00669 
00670 #ifdef SIGBUS
00671   m.assign ("BUS", SIGBUS);
00672 #endif
00673 
00674 #ifdef SIGCHLD
00675   m.assign ("CHLD", SIGCHLD);
00676 #endif
00677 
00678 #ifdef SIGCLD
00679   m.assign ("CLD", SIGCLD);
00680 #endif
00681 
00682 #ifdef SIGCONT
00683   m.assign ("CONT", SIGCONT);
00684 #endif
00685 
00686 #ifdef SIGEMT
00687   m.assign ("EMT", SIGEMT);
00688 #endif
00689 
00690 #ifdef SIGFPE
00691   m.assign ("FPE", SIGFPE);
00692 #endif
00693 
00694 #ifdef SIGHUP
00695   m.assign ("HUP", SIGHUP);
00696 #endif
00697 
00698 #ifdef SIGILL
00699   m.assign ("ILL", SIGILL);
00700 #endif
00701 
00702 #ifdef SIGINFO
00703   m.assign ("INFO", SIGINFO);
00704 #endif
00705 
00706 #ifdef SIGINT
00707   m.assign ("INT", SIGINT);
00708 #endif
00709 
00710 #ifdef SIGIOT
00711   m.assign ("IOT", SIGIOT);
00712 #endif
00713 
00714 #ifdef SIGLOST
00715   m.assign ("LOST", SIGLOST);
00716 #endif
00717 
00718 #ifdef SIGPIPE
00719   m.assign ("PIPE", SIGPIPE);
00720 #endif
00721 
00722 #ifdef SIGPOLL
00723   m.assign ("POLL", SIGPOLL);
00724 #endif
00725 
00726 #ifdef SIGPROF
00727   m.assign ("PROF", SIGPROF);
00728 #endif
00729 
00730 #ifdef SIGPWR
00731   m.assign ("PWR", SIGPWR);
00732 #endif
00733 
00734 #ifdef SIGQUIT
00735   m.assign ("QUIT", SIGQUIT);
00736 #endif
00737 
00738 #ifdef SIGSEGV
00739   m.assign ("SEGV", SIGSEGV);
00740 #endif
00741 
00742 #ifdef SIGSTOP
00743   m.assign ("STOP", SIGSTOP);
00744 #endif
00745 
00746 #ifdef SIGSYS
00747   m.assign ("SYS", SIGSYS);
00748 #endif
00749 
00750 #ifdef SIGTERM
00751   m.assign ("TERM", SIGTERM);
00752 #endif
00753 
00754 #ifdef SIGTRAP
00755   m.assign ("TRAP", SIGTRAP);
00756 #endif
00757 
00758 #ifdef SIGTSTP
00759   m.assign ("TSTP", SIGTSTP);
00760 #endif
00761 
00762 #ifdef SIGTTIN
00763   m.assign ("TTIN", SIGTTIN);
00764 #endif
00765 
00766 #ifdef SIGTTOU
00767   m.assign ("TTOU", SIGTTOU);
00768 #endif
00769 
00770 #ifdef SIGURG
00771   m.assign ("URG", SIGURG);
00772 #endif
00773 
00774 #ifdef SIGUSR1
00775   m.assign ("USR1", SIGUSR1);
00776 #endif
00777 
00778 #ifdef SIGUSR2
00779   m.assign ("USR2", SIGUSR2);
00780 #endif
00781 
00782 #ifdef SIGVTALRM
00783   m.assign ("VTALRM", SIGVTALRM);
00784 #endif
00785 
00786 #ifdef SIGIO
00787   m.assign ("IO", SIGIO);
00788 #endif
00789 
00790 #ifdef SIGWINCH
00791   m.assign ("WINCH", SIGWINCH);
00792 #endif
00793 
00794 #ifdef SIGXCPU
00795   m.assign ("XCPU", SIGXCPU);
00796 #endif
00797 
00798 #ifdef SIGXFSZ
00799   m.assign ("XFSZ", SIGXFSZ);
00800 #endif
00801 
00802   return m;
00803 }
00804 
00805 octave_child_list::octave_child_list_rep *octave_child_list::instance = 0;
00806 
00807 bool
00808 octave_child_list::instance_ok (void)
00809 {
00810   bool retval = true;
00811 
00812   if (! instance)
00813     {
00814       instance = new octave_child_list_rep ();
00815 
00816       if (instance)
00817         singleton_cleanup_list::add (cleanup_instance);
00818     }
00819 
00820   if (! instance)
00821     {
00822       ::error ("unable to create child list object!");
00823 
00824       retval = false;
00825     }
00826 
00827   return retval;
00828 }
00829 
00830 void
00831 octave_child_list::insert (pid_t pid, octave_child::child_event_handler f)
00832 {
00833   if (instance_ok ())
00834     instance->insert (pid, f);
00835 }
00836 
00837 void
00838 octave_child_list::reap (void)
00839 {
00840   if (instance_ok ())
00841     instance->reap ();
00842 }
00843 
00844 bool
00845 octave_child_list::wait (void)
00846 {
00847   return (instance_ok ()) ? instance->wait () : false;
00848 }
00849 
00850 class pid_equal
00851 {
00852 public:
00853 
00854   pid_equal (pid_t v) : val (v) { }
00855 
00856   bool operator () (const octave_child& oc) const { return oc.pid == val; }
00857 
00858 private:
00859 
00860   pid_t val;
00861 };
00862 
00863 void
00864 octave_child_list::remove (pid_t pid)
00865 {
00866   if (instance_ok ())
00867     instance->remove_if (pid_equal (pid));
00868 }
00869 
00870 #define OCL_REP octave_child_list::octave_child_list_rep
00871 
00872 void
00873 OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
00874 {
00875   append (octave_child (pid, f));
00876 }
00877 
00878 void
00879 OCL_REP::reap (void)
00880 {
00881   // Mark the record for PID invalid.
00882 
00883   for (iterator p = begin (); p != end (); p++)
00884     {
00885       // The call to the octave_child::child_event_handler might
00886       // invalidate the iterator (for example, by calling
00887       // octave_child_list::remove), so we increment the iterator
00888       // here.
00889 
00890       octave_child& oc = *p;
00891 
00892       if (oc.have_status)
00893         {
00894           oc.have_status = 0;
00895 
00896           octave_child::child_event_handler f = oc.handler;
00897 
00898           if (f && f (oc.pid, oc.status))
00899             oc.pid = -1;
00900         }
00901     }
00902 
00903   remove_if (pid_equal (-1));
00904 }
00905 
00906 // Wait on our children and record any changes in their status.
00907 
00908 bool
00909 OCL_REP::wait (void)
00910 {
00911   bool retval = false;
00912 
00913   for (iterator p = begin (); p != end (); p++)
00914     {
00915       octave_child& oc = *p;
00916 
00917       pid_t pid = oc.pid;
00918 
00919       if (pid > 0)
00920         {
00921           int status;
00922 
00923           if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
00924             {
00925               oc.have_status = 1;
00926 
00927               oc.status = status;
00928 
00929               retval = true;
00930 
00931               break;
00932             }
00933         }
00934     }
00935 
00936   return retval;
00937 }
00938 
00939 DEFUN (SIG, args, ,
00940   "-*- texinfo -*-\n\
00941 @deftypefn {Built-in Function} {} SIG ()\n\
00942 Return a structure containing Unix signal names and their defined values.\n\
00943 @end deftypefn")
00944 {
00945   octave_value retval;
00946 
00947   if (args.length () == 0)
00948     {
00949       static octave_scalar_map m = make_sig_struct ();
00950 
00951       retval = m;
00952     }
00953   else
00954     print_usage ();
00955 
00956   return retval;
00957 }
00958 
00959 /*
00960 %!error SIG (1);
00961 %!assert (isstruct (SIG ()));
00962 %!assert (! isempty (SIG ()));
00963 */
00964 
00965 DEFUN (debug_on_interrupt, args, nargout,
00966   "-*- texinfo -*-\n\
00967 @deftypefn  {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
00968 @deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\
00969 @deftypefnx {Built-in Function} {} debug_on_interrupt (@var{new_val}, \"local\")\n\
00970 Query or set the internal variable that controls whether Octave will try\n\
00971 to enter debugging mode when it receives an interrupt signal (typically\n\
00972 generated with @kbd{C-c}).  If a second interrupt signal is received\n\
00973 before reaching the debugging mode, a normal interrupt will occur.\n\
00974 \n\
00975 When called from inside a function with the \"local\" option, the variable is\n\
00976 changed locally for the function and any subroutines it calls.  The original\n\
00977 variable value is restored when exiting the function.\n\
00978 @seealso{debug_on_error, debug_on_warning}\n\
00979 @end deftypefn")
00980 {
00981   return SET_INTERNAL_VARIABLE (debug_on_interrupt);
00982 }
00983 
00984 /*
00985 %!error (debug_on_interrupt (1, 2));
00986 %!test
00987 %! orig_val = debug_on_interrupt ();
00988 %! old_val = debug_on_interrupt (! orig_val);
00989 %! assert (orig_val, old_val);
00990 %! assert (debug_on_interrupt (), ! orig_val);
00991 %! debug_on_interrupt (orig_val);
00992 %! assert (debug_on_interrupt (), orig_val);
00993 */
00994 
00995 DEFUN (sighup_dumps_octave_core, args, nargout,
00996   "-*- texinfo -*-\n\
00997 @deftypefn  {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
00998 @deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\
00999 @deftypefnx {Built-in Function} {} sighup_dumps_octave_core (@var{new_val}, \"local\")\n\
01000 Query or set the internal variable that controls whether Octave tries\n\
01001 to save all current variables to the file \"octave-core\" if it receives\n\
01002 a hangup signal.\n\
01003 \n\
01004 When called from inside a function with the \"local\" option, the variable is\n\
01005 changed locally for the function and any subroutines it calls.  The original\n\
01006 variable value is restored when exiting the function.\n\
01007 @end deftypefn")
01008 {
01009   return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
01010 }
01011 
01012 /*
01013 %!error (sighup_dumps_octave_core (1, 2));
01014 %!test
01015 %! orig_val = sighup_dumps_octave_core ();
01016 %! old_val = sighup_dumps_octave_core (! orig_val);
01017 %! assert (orig_val, old_val);
01018 %! assert (sighup_dumps_octave_core (), ! orig_val);
01019 %! sighup_dumps_octave_core (orig_val);
01020 %! assert (sighup_dumps_octave_core (), orig_val);
01021 */
01022 
01023 DEFUN (sigterm_dumps_octave_core, args, nargout,
01024   "-*- texinfo -*-\n\
01025 @deftypefn  {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
01026 @deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\
01027 @deftypefnx {Built-in Function} {} sigterm_dumps_octave_core (@var{new_val}, \"local\")\n\
01028 Query or set the internal variable that controls whether Octave tries\n\
01029 to save all current variables to the file \"octave-core\" if it receives\n\
01030 a terminate signal.\n\
01031 \n\
01032 When called from inside a function with the \"local\" option, the variable is\n\
01033 changed locally for the function and any subroutines it calls.  The original\n\
01034 variable value is restored when exiting the function.\n\
01035 @end deftypefn")
01036 {
01037   return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
01038 }
01039 
01040 /*
01041 %!error (sigterm_dumps_octave_core (1, 2));
01042 %!test
01043 %! orig_val = sigterm_dumps_octave_core ();
01044 %! old_val = sigterm_dumps_octave_core (! orig_val);
01045 %! assert (orig_val, old_val);
01046 %! assert (sigterm_dumps_octave_core (), ! orig_val);
01047 %! sigterm_dumps_octave_core (orig_val);
01048 %! assert (sigterm_dumps_octave_core (), orig_val);
01049 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines