view libinterp/corefcn/sighandlers.cc @ 17787:175b392e91fe

Use GNU style coding conventions for code in libinterp/ * libinterp/corefcn/Cell.h, libinterp/corefcn/__contourc__.cc, libinterp/corefcn/__dispatch__.cc, libinterp/corefcn/__lin_interpn__.cc, libinterp/corefcn/__pchip_deriv__.cc, libinterp/corefcn/__qp__.cc, libinterp/corefcn/balance.cc, libinterp/corefcn/besselj.cc, libinterp/corefcn/betainc.cc, libinterp/corefcn/bitfcns.cc, libinterp/corefcn/bsxfun.cc, libinterp/corefcn/c-file-ptr-stream.cc, libinterp/corefcn/c-file-ptr-stream.h, libinterp/corefcn/cellfun.cc, libinterp/corefcn/colloc.cc, libinterp/corefcn/comment-list.h, libinterp/corefcn/conv2.cc, libinterp/corefcn/daspk.cc, libinterp/corefcn/dasrt.cc, libinterp/corefcn/dassl.cc, libinterp/corefcn/data.cc, libinterp/corefcn/debug.cc, libinterp/corefcn/defaults.cc, libinterp/corefcn/defaults.in.h, libinterp/corefcn/defun-int.h, libinterp/corefcn/defun.cc, libinterp/corefcn/det.cc, libinterp/corefcn/dirfns.cc, libinterp/corefcn/display.cc, libinterp/corefcn/dlmread.cc, libinterp/corefcn/dot.cc, libinterp/corefcn/dynamic-ld.cc, libinterp/corefcn/dynamic-ld.h, libinterp/corefcn/eig.cc, libinterp/corefcn/ellipj.cc, libinterp/corefcn/error.cc, libinterp/corefcn/error.h, libinterp/corefcn/event-queue.h, libinterp/corefcn/fft.cc, libinterp/corefcn/fft2.cc, libinterp/corefcn/fftn.cc, libinterp/corefcn/file-io.cc, libinterp/corefcn/filter.cc, libinterp/corefcn/find.cc, libinterp/corefcn/gammainc.cc, libinterp/corefcn/gcd.cc, libinterp/corefcn/getgrent.cc, libinterp/corefcn/getpwent.cc, libinterp/corefcn/getrusage.cc, libinterp/corefcn/givens.cc, libinterp/corefcn/gl-render.cc, libinterp/corefcn/gl2ps-renderer.cc, libinterp/corefcn/gl2ps-renderer.h, libinterp/corefcn/graphics.cc, libinterp/corefcn/graphics.in.h, libinterp/corefcn/gripes.cc, libinterp/corefcn/gripes.h, libinterp/corefcn/help.cc, libinterp/corefcn/hess.cc, libinterp/corefcn/hex2num.cc, libinterp/corefcn/input.cc, libinterp/corefcn/input.h, libinterp/corefcn/inv.cc, libinterp/corefcn/jit-ir.h, libinterp/corefcn/jit-typeinfo.cc, libinterp/corefcn/jit-typeinfo.h, libinterp/corefcn/jit-util.h, libinterp/corefcn/kron.cc, libinterp/corefcn/load-path.cc, libinterp/corefcn/load-path.h, libinterp/corefcn/load-save.cc, libinterp/corefcn/load-save.h, libinterp/corefcn/lookup.cc, libinterp/corefcn/ls-ascii-helper.cc, libinterp/corefcn/ls-hdf5.cc, libinterp/corefcn/ls-hdf5.h, libinterp/corefcn/ls-mat-ascii.cc, libinterp/corefcn/ls-mat-ascii.h, libinterp/corefcn/ls-mat4.cc, libinterp/corefcn/ls-mat5.cc, libinterp/corefcn/ls-mat5.h, libinterp/corefcn/ls-oct-ascii.cc, libinterp/corefcn/lsode.cc, libinterp/corefcn/lu.cc, libinterp/corefcn/luinc.cc, libinterp/corefcn/mappers.cc, libinterp/corefcn/matrix_type.cc, libinterp/corefcn/max.cc, libinterp/corefcn/md5sum.cc, libinterp/corefcn/mex.cc, libinterp/corefcn/mexproto.h, libinterp/corefcn/mgorth.cc, libinterp/corefcn/mxarray.in.h, libinterp/corefcn/nproc.cc, libinterp/corefcn/oct-hist.cc, libinterp/corefcn/oct-lvalue.h, libinterp/corefcn/oct-map.cc, libinterp/corefcn/oct-map.h, libinterp/corefcn/oct-obj.h, libinterp/corefcn/oct-prcstrm.h, libinterp/corefcn/oct-stdstrm.h, libinterp/corefcn/oct-stream.cc, libinterp/corefcn/oct-stream.h, libinterp/corefcn/octave-link.cc, libinterp/corefcn/octave-link.h, libinterp/corefcn/pager.cc, libinterp/corefcn/pinv.cc, libinterp/corefcn/pr-output.cc, libinterp/corefcn/procstream.h, libinterp/corefcn/profiler.cc, libinterp/corefcn/pt-jit.cc, libinterp/corefcn/pt-jit.h, libinterp/corefcn/quad.cc, libinterp/corefcn/quadcc.cc, libinterp/corefcn/qz.cc, libinterp/corefcn/rand.cc, libinterp/corefcn/rcond.cc, libinterp/corefcn/regexp.cc, libinterp/corefcn/schur.cc, libinterp/corefcn/sighandlers.cc, libinterp/corefcn/sighandlers.h, libinterp/corefcn/sparse-xdiv.cc, libinterp/corefcn/sparse-xdiv.h, libinterp/corefcn/sparse-xpow.cc, libinterp/corefcn/sparse.cc, libinterp/corefcn/spparms.cc, libinterp/corefcn/sqrtm.cc, libinterp/corefcn/str2double.cc, libinterp/corefcn/strfind.cc, libinterp/corefcn/strfns.cc, libinterp/corefcn/sub2ind.cc, libinterp/corefcn/svd.cc, libinterp/corefcn/syl.cc, libinterp/corefcn/symtab.cc, libinterp/corefcn/symtab.h, libinterp/corefcn/syscalls.cc, libinterp/corefcn/sysdep.cc, libinterp/corefcn/sysdep.h, libinterp/corefcn/time.cc, libinterp/corefcn/toplev.cc, libinterp/corefcn/toplev.h, libinterp/corefcn/tril.cc, libinterp/corefcn/txt-eng-ft.cc, libinterp/corefcn/txt-eng-ft.h, libinterp/corefcn/txt-eng.h, libinterp/corefcn/typecast.cc, libinterp/corefcn/urlwrite.cc, libinterp/corefcn/utils.cc, libinterp/corefcn/variables.cc, libinterp/corefcn/variables.h, libinterp/corefcn/xdiv.cc, libinterp/corefcn/xdiv.h, libinterp/corefcn/xnorm.h, libinterp/corefcn/xpow.cc, libinterp/corefcn/xpow.h, libinterp/corefcn/zfstream.cc, libinterp/corefcn/zfstream.h, libinterp/dldfcn/__delaunayn__.cc, libinterp/dldfcn/__dsearchn__.cc, libinterp/dldfcn/__eigs__.cc, libinterp/dldfcn/__fltk_uigetfile__.cc, libinterp/dldfcn/__glpk__.cc, libinterp/dldfcn/__init_fltk__.cc, libinterp/dldfcn/__init_gnuplot__.cc, libinterp/dldfcn/__magick_read__.cc, libinterp/dldfcn/__voronoi__.cc, libinterp/dldfcn/amd.cc, libinterp/dldfcn/ccolamd.cc, libinterp/dldfcn/chol.cc, libinterp/dldfcn/colamd.cc, libinterp/dldfcn/convhulln.cc, libinterp/dldfcn/dmperm.cc, libinterp/dldfcn/fftw.cc, libinterp/dldfcn/qr.cc, libinterp/dldfcn/symbfact.cc, libinterp/dldfcn/symrcm.cc, libinterp/dldfcn/tsearch.cc, libinterp/octave-value/ov-base-diag.cc, libinterp/octave-value/ov-base-diag.h, libinterp/octave-value/ov-base-int.cc, libinterp/octave-value/ov-base-int.h, libinterp/octave-value/ov-base-mat.h, libinterp/octave-value/ov-base-scalar.cc, libinterp/octave-value/ov-base-scalar.h, libinterp/octave-value/ov-base-sparse.cc, libinterp/octave-value/ov-base-sparse.h, libinterp/octave-value/ov-base.cc, libinterp/octave-value/ov-base.h, libinterp/octave-value/ov-bool-mat.cc, libinterp/octave-value/ov-bool-mat.h, libinterp/octave-value/ov-bool-sparse.cc, libinterp/octave-value/ov-bool-sparse.h, libinterp/octave-value/ov-bool.cc, libinterp/octave-value/ov-bool.h, libinterp/octave-value/ov-builtin.cc, libinterp/octave-value/ov-builtin.h, libinterp/octave-value/ov-cell.cc, libinterp/octave-value/ov-cell.h, libinterp/octave-value/ov-ch-mat.cc, libinterp/octave-value/ov-ch-mat.h, libinterp/octave-value/ov-class.cc, libinterp/octave-value/ov-class.h, libinterp/octave-value/ov-colon.h, libinterp/octave-value/ov-complex.cc, libinterp/octave-value/ov-complex.h, libinterp/octave-value/ov-cx-diag.cc, libinterp/octave-value/ov-cx-diag.h, libinterp/octave-value/ov-cx-mat.cc, libinterp/octave-value/ov-cx-mat.h, libinterp/octave-value/ov-cx-sparse.cc, libinterp/octave-value/ov-cx-sparse.h, libinterp/octave-value/ov-dld-fcn.h, libinterp/octave-value/ov-fcn-handle.cc, libinterp/octave-value/ov-fcn-handle.h, libinterp/octave-value/ov-fcn-inline.cc, libinterp/octave-value/ov-fcn-inline.h, libinterp/octave-value/ov-fcn.h, libinterp/octave-value/ov-float.cc, libinterp/octave-value/ov-float.h, libinterp/octave-value/ov-flt-complex.cc, libinterp/octave-value/ov-flt-complex.h, libinterp/octave-value/ov-flt-cx-diag.cc, libinterp/octave-value/ov-flt-cx-diag.h, libinterp/octave-value/ov-flt-cx-mat.cc, libinterp/octave-value/ov-flt-cx-mat.h, libinterp/octave-value/ov-flt-re-diag.cc, libinterp/octave-value/ov-flt-re-diag.h, libinterp/octave-value/ov-flt-re-mat.cc, libinterp/octave-value/ov-flt-re-mat.h, libinterp/octave-value/ov-int16.cc, libinterp/octave-value/ov-int32.cc, libinterp/octave-value/ov-int64.cc, libinterp/octave-value/ov-int8.cc, libinterp/octave-value/ov-intx.h, libinterp/octave-value/ov-java.cc, libinterp/octave-value/ov-lazy-idx.h, libinterp/octave-value/ov-mex-fcn.cc, libinterp/octave-value/ov-mex-fcn.h, libinterp/octave-value/ov-null-mat.cc, libinterp/octave-value/ov-null-mat.h, libinterp/octave-value/ov-oncleanup.cc, libinterp/octave-value/ov-perm.cc, libinterp/octave-value/ov-perm.h, libinterp/octave-value/ov-range.cc, libinterp/octave-value/ov-range.h, libinterp/octave-value/ov-re-diag.cc, libinterp/octave-value/ov-re-diag.h, libinterp/octave-value/ov-re-mat.cc, libinterp/octave-value/ov-re-mat.h, libinterp/octave-value/ov-re-sparse.cc, libinterp/octave-value/ov-re-sparse.h, libinterp/octave-value/ov-scalar.cc, libinterp/octave-value/ov-scalar.h, libinterp/octave-value/ov-str-mat.cc, libinterp/octave-value/ov-str-mat.h, libinterp/octave-value/ov-struct.cc, libinterp/octave-value/ov-struct.h, libinterp/octave-value/ov-type-conv.h, libinterp/octave-value/ov-typeinfo.cc, libinterp/octave-value/ov-typeinfo.h, libinterp/octave-value/ov-uint16.cc, libinterp/octave-value/ov-uint32.cc, libinterp/octave-value/ov-uint64.cc, libinterp/octave-value/ov-uint8.cc, libinterp/octave-value/ov-usr-fcn.cc, libinterp/octave-value/ov-usr-fcn.h, libinterp/octave-value/ov.cc, libinterp/octave-value/ov.h, libinterp/octave.cc, libinterp/operators/op-b-bm.cc, libinterp/operators/op-b-sbm.cc, libinterp/operators/op-bm-b.cc, libinterp/operators/op-bm-bm.cc, libinterp/operators/op-cdm-cdm.cc, libinterp/operators/op-chm.cc, libinterp/operators/op-class.cc, libinterp/operators/op-cm-cm.cc, libinterp/operators/op-cm-cs.cc, libinterp/operators/op-cm-s.cc, libinterp/operators/op-cm-scm.cc, libinterp/operators/op-cm-sm.cc, libinterp/operators/op-cs-cm.cc, libinterp/operators/op-cs-cs.cc, libinterp/operators/op-cs-scm.cc, libinterp/operators/op-cs-sm.cc, libinterp/operators/op-dm-dm.cc, libinterp/operators/op-dm-scm.cc, libinterp/operators/op-double-conv.cc, libinterp/operators/op-fcdm-fcdm.cc, libinterp/operators/op-fcm-fcm.cc, libinterp/operators/op-fcm-fcs.cc, libinterp/operators/op-fcm-fm.cc, libinterp/operators/op-fcm-fs.cc, libinterp/operators/op-fcs-fcm.cc, libinterp/operators/op-fcs-fcs.cc, libinterp/operators/op-fcs-fm.cc, libinterp/operators/op-fcs-fs.cc, libinterp/operators/op-fdm-fdm.cc, libinterp/operators/op-float-conv.cc, libinterp/operators/op-fm-fcm.cc, libinterp/operators/op-fm-fcs.cc, libinterp/operators/op-fm-fm.cc, libinterp/operators/op-fm-fs.cc, libinterp/operators/op-fs-fcm.cc, libinterp/operators/op-fs-fcs.cc, libinterp/operators/op-fs-fm.cc, libinterp/operators/op-fs-fs.cc, libinterp/operators/op-m-cm.cc, libinterp/operators/op-m-cs.cc, libinterp/operators/op-m-m.cc, libinterp/operators/op-m-s.cc, libinterp/operators/op-m-scm.cc, libinterp/operators/op-m-sm.cc, libinterp/operators/op-pm-scm.cc, libinterp/operators/op-range.cc, libinterp/operators/op-s-cm.cc, libinterp/operators/op-s-cs.cc, libinterp/operators/op-s-scm.cc, libinterp/operators/op-sbm-b.cc, libinterp/operators/op-sbm-bm.cc, libinterp/operators/op-sbm-sbm.cc, libinterp/operators/op-scm-cm.cc, libinterp/operators/op-scm-cs.cc, libinterp/operators/op-scm-m.cc, libinterp/operators/op-scm-s.cc, libinterp/operators/op-scm-scm.cc, libinterp/operators/op-scm-sm.cc, libinterp/operators/op-sm-cm.cc, libinterp/operators/op-sm-m.cc, libinterp/operators/op-sm-s.cc, libinterp/operators/op-sm-scm.cc, libinterp/operators/op-sm-sm.cc, libinterp/operators/op-str-m.cc, libinterp/operators/op-str-s.cc, libinterp/operators/op-str-str.cc, libinterp/operators/ops.h, libinterp/parse-tree/lex.h, libinterp/parse-tree/parse.h, libinterp/parse-tree/pt-arg-list.cc, libinterp/parse-tree/pt-arg-list.h, libinterp/parse-tree/pt-assign.cc, libinterp/parse-tree/pt-assign.h, libinterp/parse-tree/pt-binop.cc, libinterp/parse-tree/pt-binop.h, libinterp/parse-tree/pt-bp.h, libinterp/parse-tree/pt-cbinop.cc, libinterp/parse-tree/pt-check.cc, libinterp/parse-tree/pt-colon.cc, libinterp/parse-tree/pt-colon.h, libinterp/parse-tree/pt-const.cc, libinterp/parse-tree/pt-decl.cc, libinterp/parse-tree/pt-decl.h, libinterp/parse-tree/pt-eval.cc, libinterp/parse-tree/pt-except.h, libinterp/parse-tree/pt-exp.h, libinterp/parse-tree/pt-fcn-handle.cc, libinterp/parse-tree/pt-id.cc, libinterp/parse-tree/pt-id.h, libinterp/parse-tree/pt-idx.cc, libinterp/parse-tree/pt-idx.h, libinterp/parse-tree/pt-loop.h, libinterp/parse-tree/pt-mat.cc, libinterp/parse-tree/pt-misc.cc, libinterp/parse-tree/pt-misc.h, libinterp/parse-tree/pt-pr-code.cc, libinterp/parse-tree/pt-select.h, libinterp/parse-tree/pt-stmt.h, libinterp/parse-tree/token.h, libinterp/version.cc: Use GNU style coding conventions for code in libinterp/
author Rik <rik@octave.org>
date Mon, 28 Oct 2013 19:51:46 -0700
parents b5d58667d32d
children 870f3e12e163
line wrap: on
line source

/*

Copyright (C) 1993-2013 John W. Eaton

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cstdlib>

#include <iostream>
#include <new>

#include <sys/types.h>
#include <unistd.h>

#include "cmd-edit.h"
#include "oct-syscalls.h"
#include "quit.h"
#include "singleton-cleanup.h"

#include "debug.h"
#include "defun.h"
#include "error.h"
#include "input.h"
#include "load-save.h"
#include "oct-map.h"
#include "pager.h"
#include "pt-bp.h"
#include "pt-eval.h"
#include "sighandlers.h"
#include "sysdep.h"
#include "syswait.h"
#include "toplev.h"
#include "utils.h"
#include "variables.h"

// Nonzero means we have already printed a message for this series of
// SIGPIPES.  We assume that the writer will eventually give up.
int pipe_handler_error_count = 0;

// TRUE means we can be interrupted.
bool can_interrupt = false;

// TRUE means we should try to enter the debugger on SIGINT.
bool Vdebug_on_interrupt = false;

// Allow users to avoid writing octave-workspace for SIGHUP (sent by
// closing gnome-terminal, for example).  Note that this variable has
// no effect if Vcrash_dumps_octave_core is FALSE.
static bool Vsighup_dumps_octave_core = true;

// Similar to Vsighup_dumps_octave_core, but for SIGTERM signal.
static bool Vsigterm_dumps_octave_core = true;

// List of signals we have caught since last call to octave_signal_handler.
static bool octave_signals_caught[NSIG];

// Signal handler return type.
#ifndef BADSIG
#define BADSIG (void (*)(int))-1
#endif

// The following is a workaround for an apparent bug in GCC 4.1.2 and
// possibly earlier versions.  See Octave bug report #30685 for details.
#if defined (__GNUC__)
# if ! (__GNUC__ > 4 \
        || (__GNUC__ == 4 && (__GNUC_MINOR__ > 1 \
                              || (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ > 2))))
#  undef GNULIB_NAMESPACE
#  define GNULIB_NAMESPACE
#  warning "disabling GNULIB_NAMESPACE for signal functions -- consider upgrading to a current version of GCC"
# endif
#endif

#define BLOCK_SIGNAL(sig, nvar, ovar) \
  do \
    { \
      GNULIB_NAMESPACE::sigemptyset (&nvar); \
      GNULIB_NAMESPACE::sigaddset (&nvar, sig); \
      GNULIB_NAMESPACE::sigemptyset (&ovar); \
      GNULIB_NAMESPACE::sigprocmask (SIG_BLOCK, &nvar, &ovar); \
    } \
  while (0)

#if !defined (SIGCHLD) && defined (SIGCLD)
#define SIGCHLD SIGCLD
#endif

#define BLOCK_CHILD(nvar, ovar) BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
#define UNBLOCK_CHILD(ovar) GNULIB_NAMESPACE::sigprocmask (SIG_SETMASK, &ovar, 0)

// Called from octave_quit () to actually do something about the signals
// we have caught.

void
octave_signal_handler (void)
{
  // The list of signals is relatively short, so we will just go
  // linearly through the list.

  for (int i = 0; i < NSIG; i++)
    {
      if (octave_signals_caught[i])
        {
          octave_signals_caught[i] = false;

          switch (i)
            {
#ifdef SIGCHLD
            case SIGCHLD:
              {
                volatile octave_interrupt_handler saved_interrupt_handler
                  = octave_ignore_interrupts ();

                sigset_t set, oset;

                BLOCK_CHILD (set, oset);

                octave_child_list::wait ();

                octave_set_interrupt_handler (saved_interrupt_handler);

                UNBLOCK_CHILD (oset);

                octave_child_list::reap ();
              }
              break;
#endif

            case SIGFPE:
              std::cerr << "warning: floating point exception" << std::endl;
              break;

#ifdef SIGPIPE
            case SIGPIPE:
              std::cerr << "warning: broken pipe" << std::endl;
              break;
#endif
            }
        }
    }
}

static void
my_friendly_exit (const char *sig_name, int sig_number,
                  bool save_vars = true)
{
  static bool been_there_done_that = false;

  if (been_there_done_that)
    {
#if defined (SIGABRT)
      octave_set_signal_handler (SIGABRT, SIG_DFL);
#endif

      std::cerr << "panic: attempted clean up apparently failed -- aborting...\n";

      MINGW_SIGNAL_CLEANUP ();

      abort ();
    }
  else
    {
      been_there_done_that = true;

      std::cerr << "panic: " << sig_name << " -- stopping myself...\n";

      if (save_vars)
        dump_octave_core ();

      if (sig_number < 0)
        {
          MINGW_SIGNAL_CLEANUP ();

          exit (1);
        }
      else
        {
          octave_set_signal_handler (sig_number, SIG_DFL);

          GNULIB_NAMESPACE::raise (sig_number);
        }
    }
}

sig_handler *
octave_set_signal_handler (int sig, sig_handler *handler,
                           bool restart_syscalls)
{
  struct sigaction act, oact;

  act.sa_handler = handler;
  act.sa_flags = 0;

#if defined (SIGALRM)
  if (sig == SIGALRM)
    {
#if defined (SA_INTERRUPT)
      act.sa_flags |= SA_INTERRUPT;
#endif
    }
#endif
#if defined (SA_RESTART)
#if defined (SIGALRM)
  else
#endif
  // FIXME -- Do we also need to explicitly disable SA_RESTART?
  if (restart_syscalls)
    act.sa_flags |= SA_RESTART;
#endif

  GNULIB_NAMESPACE::sigemptyset (&act.sa_mask);
  GNULIB_NAMESPACE::sigemptyset (&oact.sa_mask);

  GNULIB_NAMESPACE::sigaction (sig, &act, &oact);

  return oact.sa_handler;
}

static void
generic_sig_handler (int sig)
{
  my_friendly_exit (strsignal (sig), sig);
}

// Handle SIGCHLD.

#ifdef SIGCHLD
static void
sigchld_handler (int /* sig */)
{
  octave_signal_caught = 1;

  octave_signals_caught[SIGCHLD] = true;
}
#endif /* defined (SIGCHLD) */

#ifdef SIGFPE
#if defined (__alpha__)
static void
sigfpe_handler (int /* sig */)
{
  if (can_interrupt && octave_interrupt_state >= 0)
    {
      octave_signal_caught = 1;

      octave_signals_caught[SIGFPE] = true;

      octave_interrupt_state++;
    }
}
#endif /* defined (__alpha__) */
#endif /* defined (SIGFPE) */

#if defined (SIGHUP) || defined (SIGTERM)
static void
sig_hup_or_term_handler (int sig)
{
  switch (sig)
    {
#if defined (SIGHUP)
    case SIGHUP:
      {
        if (Vsighup_dumps_octave_core)
          dump_octave_core ();
      }
      break;
#endif

#if defined (SIGTERM)
    case SIGTERM:
      {
        if (Vsigterm_dumps_octave_core)
          dump_octave_core ();
      }
      break;
#endif

    default:
      break;
    }

  clean_up_and_exit (0);
}
#endif

#if 0
#if defined (SIGWINCH)
static void
sigwinch_handler (int /* sig */)
{
  command_editor::resize_terminal ();
}
#endif
#endif

// Handle SIGINT by restarting the parser (see octave.cc).
//
// This also has to work for SIGBREAK (on systems that have it), so we
// use the value of sig, instead of just assuming that it is called
// for SIGINT only.

static void
user_abort (const char *sig_name, int sig_number)
{
  if (! octave_initialized)
    exit (1);

  if (can_interrupt)
    {
      if (Vdebug_on_interrupt)
        {
          if (! octave_debug_on_interrupt_state)
            {
              tree_evaluator::debug_mode = true;
              octave_debug_on_interrupt_state = true;

              return;
            }
          else
            {
              // Clear the flag and do normal interrupt stuff.

              tree_evaluator::debug_mode
                = bp_table::have_breakpoints () || Vdebugging;
              octave_debug_on_interrupt_state = false;
            }
        }

      if (octave_interrupt_immediately)
        {
          if (octave_interrupt_state == 0)
            octave_interrupt_state = 1;

          octave_jump_to_enclosing_context ();
        }
      else
        {
          // If we are already cleaning up from a previous interrupt,
          // take note of the fact that another interrupt signal has
          // arrived.

          if (octave_interrupt_state < 0)
            octave_interrupt_state = 0;

          octave_signal_caught = 1;
          octave_interrupt_state++;

          if (interactive && octave_interrupt_state == 2)
            std::cerr << "Press Control-C again to abort." << std::endl;

          if (octave_interrupt_state >= 3)
            my_friendly_exit (sig_name, sig_number, true);
        }
    }

}

static void
sigint_handler (int sig)
{
  user_abort (strsignal (sig), sig);
}

#ifdef SIGPIPE
static void
sigpipe_handler (int /* sig */)
{
  octave_signal_caught = 1;

  octave_signals_caught[SIGPIPE] = true;

  // Don't loop forever on account of this.

  if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0)
    octave_interrupt_state++;
}
#endif /* defined (SIGPIPE) */

octave_interrupt_handler
octave_catch_interrupts (void)
{
  octave_interrupt_handler retval;

#ifdef SIGINT
  retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler);
#endif

#ifdef SIGBREAK
  retval.brk_handler = octave_set_signal_handler (SIGBREAK, sigint_handler);
#endif

  return retval;
}

octave_interrupt_handler
octave_ignore_interrupts (void)
{
  octave_interrupt_handler retval;

#ifdef SIGINT
  retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
#endif

#ifdef SIGBREAK
  retval.brk_handler = octave_set_signal_handler (SIGBREAK, SIG_IGN);
#endif

  return retval;
}

octave_interrupt_handler
octave_set_interrupt_handler (const volatile octave_interrupt_handler& h,
                              bool restart_syscalls)
{
  octave_interrupt_handler retval;

#ifdef SIGINT
  retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler,
                                                  restart_syscalls);
#endif

#ifdef SIGBREAK
  retval.brk_handler = octave_set_signal_handler (SIGBREAK, h.brk_handler,
                                                  restart_syscalls);
#endif

  return retval;
}

// Install all the handlers for the signals we might care about.

void
install_signal_handlers (void)
{
  for (int i = 0; i < NSIG; i++)
    octave_signals_caught[i] = false;

  octave_catch_interrupts ();

#ifdef SIGABRT
  octave_set_signal_handler (SIGABRT, generic_sig_handler);
#endif

#ifdef SIGALRM
  octave_set_signal_handler (SIGALRM, generic_sig_handler);
#endif

#ifdef SIGBUS
  octave_set_signal_handler (SIGBUS, generic_sig_handler);
#endif

#ifdef SIGCHLD
  octave_set_signal_handler (SIGCHLD, sigchld_handler);
#endif

  // SIGCLD
  // SIGCONT

#ifdef SIGEMT
  octave_set_signal_handler (SIGEMT, generic_sig_handler);
#endif

#ifdef SIGFPE
#if defined (__alpha__)
  octave_set_signal_handler (SIGFPE, sigfpe_handler);
#else
  octave_set_signal_handler (SIGFPE, generic_sig_handler);
#endif
#endif

#ifdef SIGHUP
  octave_set_signal_handler (SIGHUP, sig_hup_or_term_handler);
#endif

#ifdef SIGILL
  octave_set_signal_handler (SIGILL, generic_sig_handler);
#endif

  // SIGINFO
  // SIGINT

#ifdef SIGIOT
  octave_set_signal_handler (SIGIOT, generic_sig_handler);
#endif

#ifdef SIGLOST
  octave_set_signal_handler (SIGLOST, generic_sig_handler);
#endif

#ifdef SIGPIPE
  octave_set_signal_handler (SIGPIPE, sigpipe_handler);
#endif

#ifdef SIGPOLL
  octave_set_signal_handler (SIGPOLL, SIG_IGN);
#endif

  // SIGPROF
  // SIGPWR

#ifdef SIGQUIT
  octave_set_signal_handler (SIGQUIT, generic_sig_handler);
#endif

#ifdef SIGSEGV
  octave_set_signal_handler (SIGSEGV, generic_sig_handler);
#endif

  // SIGSTOP

#ifdef SIGSYS
  octave_set_signal_handler (SIGSYS, generic_sig_handler);
#endif

#ifdef SIGTERM
  octave_set_signal_handler (SIGTERM, sig_hup_or_term_handler);
#endif

#ifdef SIGTRAP
  octave_set_signal_handler (SIGTRAP, generic_sig_handler);
#endif

  // SIGTSTP
  // SIGTTIN
  // SIGTTOU
  // SIGURG

#ifdef SIGUSR1
  octave_set_signal_handler (SIGUSR1, generic_sig_handler);
#endif

#ifdef SIGUSR2
  octave_set_signal_handler (SIGUSR2, generic_sig_handler);
#endif

#ifdef SIGVTALRM
  octave_set_signal_handler (SIGVTALRM, generic_sig_handler);
#endif

#ifdef SIGIO
  octave_set_signal_handler (SIGIO, SIG_IGN);
#endif

#if 0
#ifdef SIGWINCH
  octave_set_signal_handler (SIGWINCH, sigwinch_handler);
#endif
#endif

#ifdef SIGXCPU
  octave_set_signal_handler (SIGXCPU, generic_sig_handler);
#endif

#ifdef SIGXFSZ
  octave_set_signal_handler (SIGXFSZ, generic_sig_handler);
#endif

}

static octave_scalar_map
make_sig_struct (void)
{
  octave_scalar_map m;

#ifdef SIGABRT
  m.assign ("ABRT", SIGABRT);
#endif

#ifdef SIGALRM
  m.assign ("ALRM", SIGALRM);
#endif

#ifdef SIGBUS
  m.assign ("BUS", SIGBUS);
#endif

#ifdef SIGCHLD
  m.assign ("CHLD", SIGCHLD);
#endif

#ifdef SIGCLD
  m.assign ("CLD", SIGCLD);
#endif

#ifdef SIGCONT
  m.assign ("CONT", SIGCONT);
#endif

#ifdef SIGEMT
  m.assign ("EMT", SIGEMT);
#endif

#ifdef SIGFPE
  m.assign ("FPE", SIGFPE);
#endif

#ifdef SIGHUP
  m.assign ("HUP", SIGHUP);
#endif

#ifdef SIGILL
  m.assign ("ILL", SIGILL);
#endif

#ifdef SIGINFO
  m.assign ("INFO", SIGINFO);
#endif

#ifdef SIGINT
  m.assign ("INT", SIGINT);
#endif

#ifdef SIGIO
  m.assign ("IO", SIGIO);
#endif

#ifdef SIGIOT
  m.assign ("IOT", SIGIOT);
#endif

#ifdef SIGKILL
  m.assign ("KILL", SIGKILL);
#endif

#ifdef SIGLOST
  m.assign ("LOST", SIGLOST);
#endif

#ifdef SIGPIPE
  m.assign ("PIPE", SIGPIPE);
#endif

#ifdef SIGPOLL
  m.assign ("POLL", SIGPOLL);
#endif

#ifdef SIGPROF
  m.assign ("PROF", SIGPROF);
#endif

#ifdef SIGPWR
  m.assign ("PWR", SIGPWR);
#endif

#ifdef SIGQUIT
  m.assign ("QUIT", SIGQUIT);
#endif

#ifdef SIGSEGV
  m.assign ("SEGV", SIGSEGV);
#endif

#ifdef SIGSTKFLT
  m.assign ("STKFLT", SIGSTKFLT);
#endif

#ifdef SIGSTOP
  m.assign ("STOP", SIGSTOP);
#endif

#ifdef SIGSYS
  m.assign ("SYS", SIGSYS);
#endif

#ifdef SIGTERM
  m.assign ("TERM", SIGTERM);
#endif

#ifdef SIGTRAP
  m.assign ("TRAP", SIGTRAP);
#endif

#ifdef SIGTSTP
  m.assign ("TSTP", SIGTSTP);
#endif

#ifdef SIGTTIN
  m.assign ("TTIN", SIGTTIN);
#endif

#ifdef SIGTTOU
  m.assign ("TTOU", SIGTTOU);
#endif

#ifdef SIGUNUSED
  m.assign ("UNUSED", SIGUNUSED);
#endif

#ifdef SIGURG
  m.assign ("URG", SIGURG);
#endif

#ifdef SIGUSR1
  m.assign ("USR1", SIGUSR1);
#endif

#ifdef SIGUSR2
  m.assign ("USR2", SIGUSR2);
#endif

#ifdef SIGVTALRM
  m.assign ("VTALRM", SIGVTALRM);
#endif

#ifdef SIGWINCH
  m.assign ("WINCH", SIGWINCH);
#endif

#ifdef SIGXCPU
  m.assign ("XCPU", SIGXCPU);
#endif

#ifdef SIGXFSZ
  m.assign ("XFSZ", SIGXFSZ);
#endif

  return m;
}

octave_child_list::octave_child_list_rep *octave_child_list::instance = 0;

bool
octave_child_list::instance_ok (void)
{
  bool retval = true;

  if (! instance)
    {
      instance = new octave_child_list_rep ();

      if (instance)
        singleton_cleanup_list::add (cleanup_instance);
    }

  if (! instance)
    {
      ::error ("unable to create child list object!");

      retval = false;
    }

  return retval;
}

void
octave_child_list::insert (pid_t pid, octave_child::child_event_handler f)
{
  if (instance_ok ())
    instance->insert (pid, f);
}

void
octave_child_list::reap (void)
{
  if (instance_ok ())
    instance->reap ();
}

bool
octave_child_list::wait (void)
{
  return (instance_ok ()) ? instance->wait () : false;
}

class pid_equal
{
public:

  pid_equal (pid_t v) : val (v) { }

  bool operator () (const octave_child& oc) const { return oc.pid == val; }

private:

  pid_t val;
};

void
octave_child_list::remove (pid_t pid)
{
  if (instance_ok ())
    instance->remove_if (pid_equal (pid));
}

#define OCL_REP octave_child_list::octave_child_list_rep

void
OCL_REP::insert (pid_t pid, octave_child::child_event_handler f)
{
  append (octave_child (pid, f));
}

void
OCL_REP::reap (void)
{
  // Mark the record for PID invalid.

  for (iterator p = begin (); p != end (); p++)
    {
      // The call to the octave_child::child_event_handler might
      // invalidate the iterator (for example, by calling
      // octave_child_list::remove), so we increment the iterator
      // here.

      octave_child& oc = *p;

      if (oc.have_status)
        {
          oc.have_status = 0;

          octave_child::child_event_handler f = oc.handler;

          if (f && f (oc.pid, oc.status))
            oc.pid = -1;
        }
    }

  remove_if (pid_equal (-1));
}

// Wait on our children and record any changes in their status.

bool
OCL_REP::wait (void)
{
  bool retval = false;

  for (iterator p = begin (); p != end (); p++)
    {
      octave_child& oc = *p;

      pid_t pid = oc.pid;

      if (pid > 0)
        {
          int status;

          if (octave_syscalls::waitpid (pid, &status, WNOHANG) > 0)
            {
              oc.have_status = 1;

              oc.status = status;

              retval = true;

              break;
            }
        }
    }

  return retval;
}

DEFUN (SIG, args, ,
       "-*- texinfo -*-\n\
@deftypefn {Built-in Function} {} SIG ()\n\
Return a structure containing Unix signal names and their defined values.\n\
@end deftypefn")
{
  octave_value retval;

  if (args.length () == 0)
    {
      static octave_scalar_map m = make_sig_struct ();

      retval = m;
    }
  else
    print_usage ();

  return retval;
}

/*
%!assert (isstruct (SIG ()))
%!assert (! isempty (SIG ()))

%!error SIG (1)
*/

DEFUN (debug_on_interrupt, args, nargout,
       "-*- texinfo -*-\n\
@deftypefn  {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
@deftypefnx {Built-in Function} {@var{old_val} =} debug_on_interrupt (@var{new_val})\n\
@deftypefnx {Built-in Function} {} debug_on_interrupt (@var{new_val}, \"local\")\n\
Query or set the internal variable that controls whether Octave will try\n\
to enter debugging mode when it receives an interrupt signal (typically\n\
generated with @kbd{C-c}).  If a second interrupt signal is received\n\
before reaching the debugging mode, a normal interrupt will occur.\n\
\n\
When called from inside a function with the @qcode{\"local\"} option, the\n\
variable is changed locally for the function and any subroutines it calls.  \n\
The original variable value is restored when exiting the function.\n\
@seealso{debug_on_error, debug_on_warning}\n\
@end deftypefn")
{
  return SET_INTERNAL_VARIABLE (debug_on_interrupt);
}

/*
%!test
%! orig_val = debug_on_interrupt ();
%! old_val = debug_on_interrupt (! orig_val);
%! assert (orig_val, old_val);
%! assert (debug_on_interrupt (), ! orig_val);
%! debug_on_interrupt (orig_val);
%! assert (debug_on_interrupt (), orig_val);

%!error (debug_on_interrupt (1, 2))
*/

DEFUN (sighup_dumps_octave_core, args, nargout,
       "-*- texinfo -*-\n\
@deftypefn  {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
@deftypefnx {Built-in Function} {@var{old_val} =} sighup_dumps_octave_core (@var{new_val})\n\
@deftypefnx {Built-in Function} {} sighup_dumps_octave_core (@var{new_val}, \"local\")\n\
Query or set the internal variable that controls whether Octave tries\n\
to save all current variables to the file @file{octave-workspace} if it\n\
receives a hangup signal.\n\
\n\
When called from inside a function with the @qcode{\"local\"} option, the\n\
variable is changed locally for the function and any subroutines it calls.  \n\
The original variable value is restored when exiting the function.\n\
@end deftypefn")
{
  return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
}

/*
%!test
%! orig_val = sighup_dumps_octave_core ();
%! old_val = sighup_dumps_octave_core (! orig_val);
%! assert (orig_val, old_val);
%! assert (sighup_dumps_octave_core (), ! orig_val);
%! sighup_dumps_octave_core (orig_val);
%! assert (sighup_dumps_octave_core (), orig_val);

%!error (sighup_dumps_octave_core (1, 2))
*/

DEFUN (sigterm_dumps_octave_core, args, nargout,
       "-*- texinfo -*-\n\
@deftypefn  {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
@deftypefnx {Built-in Function} {@var{old_val} =} sigterm_dumps_octave_core (@var{new_val})\n\
@deftypefnx {Built-in Function} {} sigterm_dumps_octave_core (@var{new_val}, \"local\")\n\
Query or set the internal variable that controls whether Octave tries\n\
to save all current variables to the file @file{octave-workspace} if it\n\
receives a terminate signal.\n\
\n\
When called from inside a function with the @qcode{\"local\"} option, the\n\
variable is changed locally for the function and any subroutines it calls.  \n\
The original variable value is restored when exiting the function.\n\
@end deftypefn")
{
  return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
}

/*
%!test
%! orig_val = sigterm_dumps_octave_core ();
%! old_val = sigterm_dumps_octave_core (! orig_val);
%! assert (orig_val, old_val);
%! assert (sigterm_dumps_octave_core (), ! orig_val);
%! sigterm_dumps_octave_core (orig_val);
%! assert (sigterm_dumps_octave_core (), orig_val);

%!error (sigterm_dumps_octave_core (1, 2))
*/