/* abort.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */

#include <stdlib.h>
#include <signal.h>
#include <emx/startup.h>

static sig_atomic_t abort_flag = 0;

void abort (void)
{
  sigset_t set;
  struct sigaction act;

  /* Special handling if there's a signal-catching function installed
     and SIGABRT is not blocked: do not yet call _cleanup(). */

  if (_sigaction (SIGABRT, NULL, &act) == 0
      && act.sa_handler != SIG_IGN && act.sa_handler != SIG_DFL
      && _sigemptyset (&set) == 0
      && _sigprocmask (SIG_SETMASK, NULL, &set) == 0
      && _sigismember (&set, SIGABRT) == 0)
    {
      /* Raise SIGABRT.  Note that this is not guaranteed to terminate
         the process. */

      raise (SIGABRT);
    }

  /* Install SIG_DFL for SIGABRT. */

  act.sa_handler = SIG_DFL;
  _sigemptyset (&act.sa_mask);
  act.sa_flags = 0;
  _sigaction (SIGABRT, &act, NULL);

  /* Clean up the C library only once. */

  if (abort_flag++ == 0)
    _cleanup ();

  /* Unblock SIGABRT. */

  _sigemptyset (&set);
  _sigaddset (&set, SIGABRT);
  _sigprocmask (SIG_UNBLOCK, &set, NULL);

  /* Raise SIGABRT again. */

  raise (SIGABRT);

  /* This should not get reached. */

  _exit (3);
}
