home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / octave-2.1.23 / src / sighandlers.cc < prev    next >
C/C++ Source or Header  |  2000-01-15  |  19KB  |  822 lines

  1. /*
  2.  
  3. Copyright (C) 1996, 1997 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. /* Modified by Klaus Gebhardt, 1995 - 1996 */
  24.  
  25. #ifdef HAVE_CONFIG_H
  26. #include <config.h>
  27. #endif
  28.  
  29. #include <cstdlib>
  30. #include <csignal>
  31.  
  32. #include <new>
  33.  
  34. #include <iostream.h>
  35.  
  36. #ifdef HAVE_UNISTD_H
  37. #ifdef HAVE_SYS_TYPES_H
  38. #include <sys/types.h>
  39. #endif
  40. #include <unistd.h>
  41. #endif
  42.  
  43. #include "cmd-edit.h"
  44.  
  45. #ifdef __EMX__
  46. #include <float.h>
  47. #include <sys/uflags.h>
  48. #endif
  49.  
  50. #include "error.h"
  51. #include "load-save.h"
  52. #include "pager.h"
  53. #include "sighandlers.h"
  54. #include "syswait.h"
  55. #include "toplev.h"
  56. #include "utils.h"
  57.  
  58. // Nonzero means we have already printed a message for this series of
  59. // SIGPIPES.  We assume that the writer will eventually give up.
  60. int pipe_handler_error_count = 0;
  61.  
  62. // TRUE means we can be interrupted.
  63. bool can_interrupt = false;
  64.  
  65. // Allow us to save the signal mask and then restore it to the most
  66. // recently saved value.  This is necessary when using the POSIX
  67. // signal handling interface on some systems calling longjmp out of
  68. // the signal handler to get to the top level on an interrupt doesn't
  69. // restore the original signal mask.  Alternatively, we could use
  70. // sigsetjmp/siglongjmp, but saving and restoring the signal mask
  71. // ourselves works ok and seems simpler just now.
  72.  
  73. #if defined (HAVE_POSIX_SIGNALS)
  74. static sigset_t octave_signal_mask;
  75. #endif
  76.  
  77. #if RETSIGTYPE == void
  78. #define SIGHANDLER_RETURN(status) return
  79. #else
  80. #define SIGHANDLER_RETURN(status) return status
  81. #endif
  82.  
  83. #if defined (MUST_REINSTALL_SIGHANDLERS)
  84. #define MAYBE_REINSTALL_SIGHANDLER(sig, handler) \
  85.   octave_set_signal_handler (sig, handler)
  86. #define REINSTALL_USES_SIG 1
  87. #else
  88. #define MAYBE_REINSTALL_SIGHANDLER(sig, handler) \
  89.   do { } while (0)
  90. #endif
  91.  
  92. #if defined (__EMX__)
  93. #define MAYBE_ACK_SIGNAL(sig) \
  94.   signal (sig, SIG_ACK)
  95. #define ACK_USES_SIG 1
  96. #else
  97. #define MAYBE_ACK_SIGNAL(sig) \
  98.   do { } while (0)
  99. #endif
  100.  
  101. #if defined (SIGABRT)
  102. #define OCTAVE_MEMORY_EXHAUSTED_ERROR SIGABRT
  103. #else
  104. #define OCTAVE_MEMORY_EXHAUSTED_ERROR (-1)
  105. #endif
  106.  
  107. void
  108. octave_save_signal_mask (void)
  109. {
  110. #if defined (HAVE_POSIX_SIGNALS)
  111.   sigprocmask (0, 0, &octave_signal_mask);
  112. #endif
  113. }
  114.  
  115. void
  116. octave_restore_signal_mask (void)
  117. {
  118. #if defined (HAVE_POSIX_SIGNALS)
  119.   sigprocmask (SIG_SETMASK, &octave_signal_mask, 0);
  120. #endif
  121. }
  122.  
  123. static void
  124. my_friendly_exit (const char *sig_name, int sig_number)
  125. {
  126.   static bool been_there_done_that = false;
  127.  
  128.   if (been_there_done_that)
  129.     {
  130. #if defined (SIGABRT)
  131.       octave_set_signal_handler (SIGABRT, SIG_DFL);
  132. #endif
  133.  
  134.       cerr << "error: attempted clean up apparently failed -- aborting...\n";
  135.  
  136.       abort ();
  137.     }
  138.   else
  139.     {
  140.       been_there_done_that = true;
  141.  
  142.       cerr << "\n\nerror: " << sig_name << " -- stopping myself...\n";
  143.  
  144.       save_user_variables ();
  145.  
  146.       if (sig_number < 0)
  147.     exit (1);
  148.       else
  149.     {
  150.       octave_set_signal_handler (sig_number, SIG_DFL);
  151.  
  152.       kill (getpid (), sig_number);
  153.     }
  154.     }
  155. }
  156.  
  157. // I know, not really a signal handler.
  158.  
  159. static void
  160. octave_new_handler (void)
  161. {
  162.   cerr << "error: memory exhausted -- trying to return to prompt\n";
  163.  
  164.   if (can_interrupt)
  165.     {
  166. #ifdef __EMX__
  167.       _uflags (_UF_SBRK_MODEL, _UF_SBRK_ARBITRARY);
  168. #endif
  169.       jump_to_top_level ();
  170.       panic_impossible ();
  171.     }
  172.   else
  173.     my_friendly_exit ("operator new", OCTAVE_MEMORY_EXHAUSTED_ERROR);
  174. }
  175.  
  176. sig_handler *
  177. octave_set_signal_handler (int sig, sig_handler *handler)
  178. {
  179. #if defined (HAVE_POSIX_SIGNALS)
  180.   struct sigaction act, oact;
  181.   act.sa_handler = handler;
  182.   act.sa_flags = 0;
  183.   sigemptyset (&act.sa_mask);
  184.   sigemptyset (&oact.sa_mask);
  185.   sigaction (sig, &act, &oact);
  186.   return oact.sa_handler;
  187. #elif defined (__EMX__)
  188.   sig_handler *signal_handler = signal (sig, handler);
  189.   MAYBE_ACK_SIGNAL(sig);
  190.   return signal_handler;
  191. #else
  192.   return signal (sig, handler);
  193. #endif
  194. }
  195.  
  196. static RETSIGTYPE
  197. generic_sig_handler (int sig)
  198. {
  199.   my_friendly_exit (sys_siglist[sig], sig);
  200.  
  201.   SIGHANDLER_RETURN (0);
  202. }
  203.  
  204. // Handle SIGCHLD.
  205.  
  206. static RETSIGTYPE
  207. sigchld_handler (int sig)
  208. {
  209.   volatile octave_interrupt_handler saved_interrupt_handler
  210.      = octave_ignore_interrupts ();
  211.  
  212.   // I wonder if this is really right, or if SIGCHLD should just be
  213.   // blocked on OS/2 systems the same as for systems with POSIX signal
  214.   // functions.
  215.  
  216. #if defined (__EMX__)
  217.   volatile sig_handler *saved_sigchld_handler
  218.     = octave_set_signal_handler (SIGCHLD, SIG_IGN);
  219. #else
  220.   sigset_t set, oset;
  221.  
  222.   BLOCK_CHILD (set, oset);
  223. #endif
  224.  
  225.   int i = 0;
  226.   int n = octave_child_list::length ();
  227.  
  228.   for (i = 0; i < n; i++)
  229.     {
  230.       octave_child& elt = octave_child_list::elem (i);
  231.  
  232.       pid_t pid = elt.pid;
  233.  
  234.       if (pid > 0)
  235.     {
  236.       int status;
  237.  
  238.       if (waitpid (pid, &status, WNOHANG) > 0)
  239.         {
  240.           elt.pid = -1;
  241.  
  242.           octave_child::dead_child_handler f = elt.handler;
  243.  
  244.           if (f)  f (pid, status);
  245.           else
  246.         {
  247.           string file = elt.filename;
  248.           unlink (file.c_str ());
  249.         }
  250.  
  251.           break;
  252.         }
  253.     }
  254.     }
  255.  
  256.   if (i == n)  waitpid (-1, NULL, WNOHANG);
  257.  
  258.   octave_set_interrupt_handler (saved_interrupt_handler);
  259.  
  260. #ifndef __EMX__
  261.   UNBLOCK_CHILD (oset);
  262. #else
  263.   octave_set_signal_handler (SIGCHLD, saved_sigchld_handler);
  264. #endif
  265.  
  266.   MAYBE_ACK_SIGNAL (SIGCHLD);
  267.  
  268.   MAYBE_REINSTALL_SIGHANDLER (SIGCHLD, sigchld_handler);
  269.  
  270.   SIGHANDLER_RETURN (0);
  271. }
  272.  
  273. #if defined (__alpha__)
  274. static RETSIGTYPE
  275. sigfpe_handler (int sig)
  276. {
  277.   MAYBE_ACK_SIGNAL (SIGFPE);
  278.  
  279.   MAYBE_REINSTALL_SIGHANDLER (SIGFPE, sigfpe_handler);
  280.  
  281.   cerr << "error: floating point exception -- trying to return to prompt\n";
  282.  
  283.   if (can_interrupt)
  284.     {
  285. #if defined (__EMX__)
  286.       _control87 (EM_INVALID | EM_DENORMAL | EM_ZERODIVIDE | EM_OVERFLOW |
  287.           EM_UNDERFLOW | EM_INEXACT, MCW_EM);
  288. #endif
  289.       jump_to_top_level ();
  290.       panic_impossible ();
  291.     }
  292.  
  293.   SIGHANDLER_RETURN (0);
  294. }
  295. #endif
  296.  
  297. #if 0
  298. #if defined (SIGWINCH)
  299. static RETSIGTYPE
  300. sigwinch_handler (int /* sig */)
  301. {
  302.   MAYBE_ACK_SIGNAL (SIGWINCH);
  303.  
  304.   MAYBE_REINSTALL_SIGHANDLER (SIGWINCH, sigwinch_handler);
  305.  
  306.   command_editor::resize_terminal ();
  307.  
  308.   SIGHANDLER_RETURN (0);
  309. }
  310. #endif
  311. #endif
  312.  
  313. // Handle SIGINT by restarting the parser (see octave.cc).
  314. //
  315. // This also has to work for SIGBREAK (on systems that have it), so we
  316. // use the value of sig, instead of just assuming that it is called
  317. // for SIGINT only.
  318.  
  319. static RETSIGTYPE
  320. #if defined (ACK_USES_SIG) || defined (REINSTALL_USES_SIG)
  321. sigint_handler (int sig)
  322. #else
  323. sigint_handler (int)
  324. #endif
  325. {
  326.   MAYBE_ACK_SIGNAL (sig);
  327.  
  328.   MAYBE_REINSTALL_SIGHANDLER (sig, sigint_handler);
  329.  
  330.   if (can_interrupt)
  331.     {
  332.       jump_to_top_level ();
  333.       panic_impossible ();
  334.     }
  335.  
  336.   SIGHANDLER_RETURN (0);
  337. }
  338.  
  339. static RETSIGTYPE
  340. sigpipe_handler (int sig)
  341. {
  342.   MAYBE_ACK_SIGNAL (SIGPIPE);
  343.  
  344.   MAYBE_REINSTALL_SIGHANDLER (SIGPIPE, sigpipe_handler);
  345.  
  346.   if (pipe_handler_error_count++ == 0)
  347.     cerr << "warning: broken pipe\n";
  348.  
  349.   // Don't loop forever on account of this.
  350.  
  351.   if (pipe_handler_error_count  > 100)
  352.     jump_to_top_level ();
  353.  
  354.   SIGHANDLER_RETURN (0);
  355. }
  356.  
  357. octave_interrupt_handler
  358. octave_catch_interrupts (void)
  359. {
  360.   octave_interrupt_handler retval;
  361.  
  362. #ifdef SIGINT
  363.   octave_set_signal_handler (SIGINT, sigint_handler);
  364.   retval.int_handler = sigint_handler;
  365.   MAYBE_ACK_SIGNAL (SIGINT);
  366. #endif
  367.  
  368. #ifdef SIGBREAK
  369.   octave_set_signal_handler (SIGBREAK, sigint_handler);
  370.   retval.brk_handler = sigint_handler;
  371.   MAYBE_ACK_SIGNAL (SIGBREAK);
  372. #endif
  373.  
  374.   return retval;
  375. }
  376.  
  377. octave_interrupt_handler
  378. octave_ignore_interrupts (void)
  379. {
  380.   octave_interrupt_handler retval;
  381.  
  382. #ifdef SIGINT
  383.   retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
  384. #endif
  385.  
  386. #ifdef SIGBREAK
  387.   retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
  388. #endif
  389.  
  390.   return retval;
  391. }
  392.  
  393. octave_interrupt_handler
  394. octave_set_interrupt_handler (RETSIGTYPE (*f)(int))
  395. {
  396.   octave_interrupt_handler retval;
  397.  
  398.   if (f)
  399.     {
  400. #ifdef SIGINT
  401.       retval.int_handler = octave_set_signal_handler (SIGINT, f);
  402.       MAYBE_ACK_SIGNAL (SIGINT);
  403. #endif
  404.  
  405. #ifdef SIGBREAK
  406.       retval.brk_handler = octave_set_signal_handler (SIGBREAK, f);
  407.       MAYBE_ACK_SIGNAL (SIGBREAK);
  408. #endif
  409.     }
  410.  
  411.   return retval;
  412. }
  413.  
  414. octave_interrupt_handler
  415. octave_set_interrupt_handler (const volatile octave_interrupt_handler& h)
  416. {
  417.   octave_interrupt_handler retval;
  418.  
  419. #ifdef SIGINT
  420.   retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler);
  421.   MAYBE_ACK_SIGNAL (SIGINT);
  422. #endif
  423.  
  424. #ifdef SIGBREAK
  425.   retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler);
  426.   MAYBE_ACK_SIGNAL (SIGBREAK);
  427. #endif
  428.  
  429.   return retval;
  430. }
  431.  
  432. // Install all the handlers for the signals we might care about.
  433.  
  434. void
  435. install_signal_handlers (void)
  436. {
  437.   set_new_handler (octave_new_handler);
  438.  
  439.   octave_catch_interrupts ();
  440.  
  441. #ifdef SIGABRT
  442.   octave_set_signal_handler (SIGABRT, generic_sig_handler);
  443. #endif
  444.  
  445. #ifdef SIGALRM
  446.   octave_set_signal_handler (SIGALRM, generic_sig_handler);
  447. #endif
  448.  
  449. #ifdef SIGBUS
  450.   octave_set_signal_handler (SIGBUS, generic_sig_handler);
  451. #endif
  452.  
  453. #ifdef SIGCHLD
  454.   octave_set_signal_handler (SIGCHLD, sigchld_handler);
  455. #endif
  456.  
  457.   // SIGCLD
  458.   // SIGCONT
  459.  
  460. #ifdef SIGEMT
  461.   octave_set_signal_handler (SIGEMT, generic_sig_handler);
  462. #endif
  463.  
  464. #ifdef SIGFPE
  465. #if defined (__alpha__)
  466.   octave_set_signal_handler (SIGFPE, sigfpe_handler);
  467. #else
  468.   octave_set_signal_handler (SIGFPE, generic_sig_handler);
  469. #endif
  470. #endif
  471.  
  472. #ifdef SIGHUP
  473.   octave_set_signal_handler (SIGHUP, generic_sig_handler);
  474. #endif
  475.  
  476. #ifdef SIGILL
  477.   octave_set_signal_handler (SIGILL, generic_sig_handler);
  478. #endif
  479.  
  480.   // SIGINFO
  481.   // SIGINT
  482.  
  483. #ifdef SIGIOT
  484.   octave_set_signal_handler (SIGIOT, generic_sig_handler);
  485. #endif
  486.  
  487. #ifdef SIGLOST
  488.   octave_set_signal_handler (SIGLOST, generic_sig_handler);
  489. #endif
  490.  
  491. #ifdef SIGPIPE
  492.   octave_set_signal_handler (SIGPIPE, sigpipe_handler);
  493. #endif
  494.  
  495. #ifdef SIGPOLL
  496.   octave_set_signal_handler (SIGPOLL, SIG_IGN);
  497. #endif
  498.  
  499. #ifdef SIGPROF
  500.   octave_set_signal_handler (SIGPROF, generic_sig_handler);
  501. #endif
  502.  
  503.   // SIGPWR
  504.  
  505. #ifdef SIGQUIT
  506.   octave_set_signal_handler (SIGQUIT, generic_sig_handler);
  507. #endif
  508.  
  509. #ifdef SIGSEGV
  510.   octave_set_signal_handler (SIGSEGV, generic_sig_handler);
  511. #endif
  512.  
  513.   // SIGSTOP
  514.  
  515. #ifdef SIGSYS
  516.   octave_set_signal_handler (SIGSYS, generic_sig_handler);
  517. #endif
  518.  
  519. #ifdef SIGTERM
  520. #ifdef __EMX__
  521.   signal (SIGTERM, SIG_DFL);
  522. #else
  523.   octave_set_signal_handler (SIGTERM, generic_sig_handler);
  524. #endif
  525. #endif
  526.  
  527. #ifdef SIGTRAP
  528.   octave_set_signal_handler (SIGTRAP, generic_sig_handler);
  529. #endif
  530.  
  531.   // SIGTSTP
  532.   // SIGTTIN
  533.   // SIGTTOU
  534.   // SIGURG
  535.  
  536. #ifdef SIGUSR1
  537.   octave_set_signal_handler (SIGUSR1, generic_sig_handler);
  538. #endif
  539.  
  540. #ifdef SIGUSR2
  541.   octave_set_signal_handler (SIGUSR2, generic_sig_handler);
  542. #endif
  543.  
  544. #ifdef SIGVTALRM
  545.   octave_set_signal_handler (SIGVTALRM, generic_sig_handler);
  546. #endif
  547.  
  548. #ifdef SIGIO
  549.   octave_set_signal_handler (SIGIO, SIG_IGN);
  550. #endif
  551.  
  552. #if 0
  553. #ifdef SIGWINCH
  554.   octave_set_signal_handler (SIGWINCH, sigwinch_handler);
  555. #endif
  556. #endif
  557.  
  558. #ifdef SIGXCPU
  559.   octave_set_signal_handler (SIGXCPU, generic_sig_handler);
  560. #endif
  561.  
  562. #ifdef SIGXFSZ
  563.   octave_set_signal_handler (SIGXFSZ, generic_sig_handler);
  564. #endif
  565. }
  566.  
  567. #ifndef HAVE_SYS_SIGLIST
  568. char *sys_siglist[NSIG + 1] =
  569. {
  570. #ifdef AIX
  571. /* AIX has changed the signals a bit */
  572.   "bogus signal",            /* 0 */
  573.   "hangup",                /* 1  SIGHUP */
  574.   "interrupt",                /* 2  SIGINT */
  575.   "quit",                /* 3  SIGQUIT */
  576.   "illegal instruction",        /* 4  SIGILL */
  577.   "trace trap",                /* 5  SIGTRAP */
  578.   "IOT instruction",            /* 6  SIGIOT */
  579.   "crash likely",            /* 7  SIGDANGER */
  580.   "floating point exception",        /* 8  SIGFPE */
  581.   "kill",                /* 9  SIGKILL */
  582.   "bus error",                /* 10 SIGBUS */
  583.   "segmentation violation",        /* 11 SIGSEGV */
  584.   "bad argument to system call",    /* 12 SIGSYS */
  585.   "write on a pipe with no one to read it", /* 13 SIGPIPE */
  586.   "alarm clock",            /* 14 SIGALRM */
  587.   "software termination signum",    /* 15 SIGTERM */
  588.   "user defined signal 1",        /* 16 SIGUSR1 */
  589.   "user defined signal 2",        /* 17 SIGUSR2 */
  590.   "death of a child",            /* 18 SIGCLD */
  591.   "power-fail restart",            /* 19 SIGPWR */
  592.   "bogus signal",            /* 20 */
  593.   "bogus signal",            /* 21 */
  594.   "bogus signal",            /* 22 */
  595.   "bogus signal",            /* 23 */
  596.   "bogus signal",            /* 24 */
  597.   "LAN I/O interrupt",            /* 25 SIGAIO */
  598.   "PTY I/O interrupt",            /* 26 SIGPTY */
  599.   "I/O intervention required",        /* 27 SIGIOINT */
  600.   "HFT grant",                /* 28 SIGGRANT */
  601.   "HFT retract",            /* 29 SIGRETRACT */
  602.   "HFT sound done",            /* 30 SIGSOUND */
  603.   "HFT input ready",            /* 31 SIGMSG */
  604. #else /* not AIX */
  605. #ifdef __EMX__
  606.   "bogus signal #0",                    /* 0 */
  607.   "hangup",                             /* 1  SIGHUP */
  608.   "interrupt (Ctrl-C)",                 /* 2  SIGINT (Ctrl-C) */
  609.   "quit",                               /* 3  SIGQUIT */
  610.   "illegal instruction",                /* 4  SIGILL */
  611.   "single step",                        /* 5  SIGTRAP */
  612.   "abort",                              /* 6  SIGABRT */
  613.   "EMT instruction",                    /* 7  SIGEMT */
  614.   "floating point exception",           /* 8  SIGFPE */
  615.   "kill",                               /* 9  SIGKILL */
  616.   "bus error",                          /* 10 SIGBUS */
  617.   "segmentation violation",             /* 11 SIGSEGV */
  618.   "bad argument to system call",        /* 12 SIGSYS */
  619.   "broken pipe",                        /* 13 SIGPIPE */
  620.   "alarm clock",                        /* 14 SIGALRM */
  621.   "software termination signum",        /* 15 SIGTERM */
  622.   "user defined signal 1",              /* 16 SIGUSR1 */
  623.   "user defined signal 2",              /* 17 SIGUSR2 */
  624.   "death of a child",                   /* 18 SIGCHLD */
  625.   "bogus signal #20",                   /* 19 */
  626.   "bogus signal #21",                   /* 20 */
  627.   "break (Ctrl-Break)",                 /* 21 SIGBREAK */
  628. #else /* not __EMX__ */
  629.   "bogus signal",            /* 0 */
  630.   "hangup",                /* 1  SIGHUP */
  631.   "interrupt",                /* 2  SIGINT */
  632.   "quit",                /* 3  SIGQUIT */
  633.   "illegal instruction",        /* 4  SIGILL */
  634.   "trace trap",                /* 5  SIGTRAP */
  635.   "IOT instruction",            /* 6  SIGIOT */
  636.   "EMT instruction",            /* 7  SIGEMT */
  637.   "floating point exception",        /* 8  SIGFPE */
  638.   "kill",                /* 9  SIGKILL */
  639.   "bus error",                /* 10 SIGBUS */
  640.   "segmentation violation",        /* 11 SIGSEGV */
  641.   "bad argument to system call",    /* 12 SIGSYS */
  642.   "write on a pipe with no one to read it", /* 13 SIGPIPE */
  643.   "alarm clock",            /* 14 SIGALRM */
  644.   "software termination signum",    /* 15 SIGTERM */
  645.   "user defined signal 1",        /* 16 SIGUSR1 */
  646.   "user defined signal 2",        /* 17 SIGUSR2 */
  647.   "death of a child",            /* 18 SIGCLD */
  648.   "power-fail restart",            /* 19 SIGPWR */
  649. #ifdef sun
  650.   "window size change",                /* 20 SIGWINCH */
  651.   "urgent socket condition",            /* 21 SIGURG */
  652.   "pollable event occured",            /* 22 SIGPOLL */
  653.   "stop (cannot be caught or ignored)", /*  23 SIGSTOP */
  654.   "user stop requested from tty",        /* 24 SIGTSTP */
  655.   "stopped process has been continued",    /* 25 SIGCONT */
  656.   "background tty read attempted",        /* 26 SIGTTIN */
  657.   "background tty write attempted",    /* 27 SIGTTOU */
  658.   "virtual timer expired",            /* 28 SIGVTALRM */
  659.   "profiling timer expired",            /* 29 SIGPROF */
  660.   "exceeded cpu limit",                /* 30 SIGXCPU */
  661.   "exceeded file size limit",            /* 31 SIGXFSZ */
  662.   "process's lwps are blocked",        /*  32 SIGWAITING */
  663.   "special signal used by thread library", /* 33 SIGLWP */
  664. #ifdef SIGFREEZE
  665.   "Special Signal Used By CPR",        /* 34 SIGFREEZE */
  666. #endif
  667. #ifdef SIGTHAW
  668.   "Special Signal Used By CPR",        /* 35 SIGTHAW */
  669. #endif
  670. #endif /* sun */
  671. #endif /* __EMX__ */
  672. #endif /* AIX */
  673.   0
  674.   };
  675. #endif
  676.  
  677. octave_child_list *octave_child_list::instance = 0;
  678.  
  679. bool
  680. octave_child_list::instance_ok (void)
  681. {
  682.   bool retval = true;
  683.  
  684.   if (! instance)
  685.     instance = new octave_child_list ();
  686.  
  687.   if (! instance)
  688.     {
  689.       ::error ("unable to create child list object!");
  690.  
  691.       retval = false;
  692.     }
  693.  
  694.   return retval;
  695. }
  696.  
  697. void
  698. octave_child_list::insert (pid_t pid, octave_child::dead_child_handler f,
  699.                string name)
  700. {
  701.   if (instance_ok ())
  702.     instance->do_insert (pid, f, name);
  703. }
  704.  
  705. void
  706. octave_child_list::remove (pid_t pid)
  707. {
  708.   if (instance_ok ())
  709.     instance->do_remove (pid);
  710. }
  711.  
  712. int
  713. octave_child_list::length (void)
  714. {
  715.   return (instance_ok ()) ? instance->do_length () : 0;
  716. }
  717.  
  718. octave_child&
  719. octave_child_list::elem (int i)
  720. {
  721.   static octave_child foo;
  722.  
  723.   return (instance_ok ()) ? instance->do_elem (i) : foo;
  724. }
  725.  
  726. void
  727. octave_child_list::do_insert (pid_t pid, octave_child::dead_child_handler f,
  728.                   string name)
  729. {
  730.   // Insert item in first open slot, increasing size of list if
  731.   // necessary.
  732.  
  733.   bool enlarge = true;
  734.  
  735.   for (int i = 0; i < curr_len; i++)
  736.     {
  737.       octave_child& tmp = list (i);
  738.  
  739.       if (tmp.pid < 0)
  740.     {
  741.       list (i) = octave_child (pid, f, name);
  742.       enlarge = false;
  743.       break;
  744.     }
  745.     }
  746.  
  747.   if (enlarge)
  748.     {
  749.       int total_len = list.length ();
  750.  
  751.       if (curr_len == total_len)
  752.     {
  753.       if (total_len == 0)
  754.         list.resize (16);
  755.       else
  756.         list.resize (total_len * 2);
  757.     }
  758.  
  759.       list (curr_len) = octave_child (pid, f, name);
  760.       curr_len++;
  761.     }
  762. }
  763.  
  764. void
  765. octave_child_list::do_remove (pid_t pid)
  766. {
  767.   // Mark the record for PID invalid.
  768.  
  769.   for (int i = 0; i < curr_len; i++)
  770.     {
  771.       octave_child& tmp = list (i);
  772.  
  773.       if (tmp.pid == pid)
  774.     {
  775.       tmp.pid = -1;
  776.  
  777.       octave_child::dead_child_handler f = tmp.handler;
  778.  
  779.       if (f)
  780.         {
  781.           int status;
  782.  
  783.           if (waitpid (pid, &status, WNOHANG) <= 0)  status = 127;
  784.  
  785.           f (pid, status);
  786.         }
  787.       else
  788.         {
  789.           string file = tmp.filename;
  790.           unlink (file.c_str ());
  791.         }
  792.  
  793.       break;
  794.     }
  795.     }
  796. }
  797.  
  798. int
  799. octave_child_list::do_length (void) const
  800. {
  801.   return curr_len;
  802. }
  803.  
  804. octave_child&
  805. octave_child_list::do_elem (int i)
  806. {
  807.   static octave_child foo;
  808.  
  809.   int n = do_length ();
  810.  
  811.   if (i >= 0 && i < n)
  812.     return list (i);
  813.   else
  814.     return foo;
  815. }
  816.  
  817. /*
  818. ;;; Local Variables: ***
  819. ;;; mode: C++ ***
  820. ;;; End: ***
  821. */
  822.