Blame m4/nocrash.m4

Packit 33f14e
# nocrash.m4 serial 4
Packit 33f14e
dnl Copyright (C) 2005, 2009-2017 Free Software Foundation, Inc.
Packit 33f14e
dnl This file is free software; the Free Software Foundation
Packit 33f14e
dnl gives unlimited permission to copy and/or distribute it,
Packit 33f14e
dnl with or without modifications, as long as this notice is preserved.
Packit 33f14e
Packit 33f14e
dnl Based on libsigsegv, from Bruno Haible and Paolo Bonzini.
Packit 33f14e
Packit 33f14e
AC_PREREQ([2.13])
Packit 33f14e
Packit 33f14e
dnl Expands to some code for use in .c programs that will cause the configure
Packit 33f14e
dnl test to exit instead of crashing. This is useful to avoid triggering
Packit 33f14e
dnl action from a background debugger and to avoid core dumps.
Packit 33f14e
dnl Usage:   ...
Packit 33f14e
dnl          ]GL_NOCRASH[
Packit 33f14e
dnl          ...
Packit 33f14e
dnl          int main() { nocrash_init(); ... }
Packit 33f14e
AC_DEFUN([GL_NOCRASH],[[
Packit 33f14e
#include <stdlib.h>
Packit 33f14e
#if defined __MACH__ && defined __APPLE__
Packit 33f14e
/* Avoid a crash on Mac OS X.  */
Packit 33f14e
#include <mach/mach.h>
Packit 33f14e
#include <mach/mach_error.h>
Packit 33f14e
#include <mach/thread_status.h>
Packit 33f14e
#include <mach/exception.h>
Packit 33f14e
#include <mach/task.h>
Packit 33f14e
#include <pthread.h>
Packit 33f14e
/* The exception port on which our thread listens.  */
Packit 33f14e
static mach_port_t our_exception_port;
Packit 33f14e
/* The main function of the thread listening for exceptions of type
Packit 33f14e
   EXC_BAD_ACCESS.  */
Packit 33f14e
static void *
Packit 33f14e
mach_exception_thread (void *arg)
Packit 33f14e
{
Packit 33f14e
  /* Buffer for a message to be received.  */
Packit 33f14e
  struct {
Packit 33f14e
    mach_msg_header_t head;
Packit 33f14e
    mach_msg_body_t msgh_body;
Packit 33f14e
    char data[1024];
Packit 33f14e
  } msg;
Packit 33f14e
  mach_msg_return_t retval;
Packit 33f14e
  /* Wait for a message on the exception port.  */
Packit 33f14e
  retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
Packit 33f14e
                     our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
Packit 33f14e
  if (retval != MACH_MSG_SUCCESS)
Packit 33f14e
    abort ();
Packit 33f14e
  exit (1);
Packit 33f14e
}
Packit 33f14e
static void
Packit 33f14e
nocrash_init (void)
Packit 33f14e
{
Packit 33f14e
  mach_port_t self = mach_task_self ();
Packit 33f14e
  /* Allocate a port on which the thread shall listen for exceptions.  */
Packit 33f14e
  if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
Packit 33f14e
      == KERN_SUCCESS) {
Packit 33f14e
    /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
Packit 33f14e
    if (mach_port_insert_right (self, our_exception_port, our_exception_port,
Packit 33f14e
                                MACH_MSG_TYPE_MAKE_SEND)
Packit 33f14e
        == KERN_SUCCESS) {
Packit 33f14e
      /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
Packit 33f14e
         for us.  */
Packit 33f14e
      exception_mask_t mask = EXC_MASK_BAD_ACCESS;
Packit 33f14e
      /* Create the thread listening on the exception port.  */
Packit 33f14e
      pthread_attr_t attr;
Packit 33f14e
      pthread_t thread;
Packit 33f14e
      if (pthread_attr_init (&attr) == 0
Packit 33f14e
          && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
Packit 33f14e
          && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
Packit 33f14e
        pthread_attr_destroy (&attr);
Packit 33f14e
        /* Replace the exception port info for these exceptions with our own.
Packit 33f14e
           Note that we replace the exception port for the entire task, not only
Packit 33f14e
           for a particular thread.  This has the effect that when our exception
Packit 33f14e
           port gets the message, the thread specific exception port has already
Packit 33f14e
           been asked, and we don't need to bother about it.
Packit 33f14e
           See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
Packit 33f14e
        task_set_exception_ports (self, mask, our_exception_port,
Packit 33f14e
                                  EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
Packit 33f14e
      }
Packit 33f14e
    }
Packit 33f14e
  }
Packit 33f14e
}
Packit 33f14e
#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit 33f14e
/* Avoid a crash on native Windows.  */
Packit 33f14e
#define WIN32_LEAN_AND_MEAN
Packit 33f14e
#include <windows.h>
Packit 33f14e
#include <winerror.h>
Packit 33f14e
static LONG WINAPI
Packit 33f14e
exception_filter (EXCEPTION_POINTERS *ExceptionInfo)
Packit 33f14e
{
Packit 33f14e
  switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
Packit 33f14e
    {
Packit 33f14e
    case EXCEPTION_ACCESS_VIOLATION:
Packit 33f14e
    case EXCEPTION_IN_PAGE_ERROR:
Packit 33f14e
    case EXCEPTION_STACK_OVERFLOW:
Packit 33f14e
    case EXCEPTION_GUARD_PAGE:
Packit 33f14e
    case EXCEPTION_PRIV_INSTRUCTION:
Packit 33f14e
    case EXCEPTION_ILLEGAL_INSTRUCTION:
Packit 33f14e
    case EXCEPTION_DATATYPE_MISALIGNMENT:
Packit 33f14e
    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
Packit 33f14e
    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
Packit 33f14e
      exit (1);
Packit 33f14e
    }
Packit 33f14e
  return EXCEPTION_CONTINUE_SEARCH;
Packit 33f14e
}
Packit 33f14e
static void
Packit 33f14e
nocrash_init (void)
Packit 33f14e
{
Packit 33f14e
  SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) exception_filter);
Packit 33f14e
}
Packit 33f14e
#else
Packit 33f14e
/* Avoid a crash on POSIX systems.  */
Packit 33f14e
#include <signal.h>
Packit 33f14e
#include <unistd.h>
Packit 33f14e
/* A POSIX signal handler.  */
Packit 33f14e
static void
Packit 33f14e
exception_handler (int sig)
Packit 33f14e
{
Packit 33f14e
  _exit (1);
Packit 33f14e
}
Packit 33f14e
static void
Packit 33f14e
nocrash_init (void)
Packit 33f14e
{
Packit 33f14e
#ifdef SIGSEGV
Packit 33f14e
  signal (SIGSEGV, exception_handler);
Packit 33f14e
#endif
Packit 33f14e
#ifdef SIGBUS
Packit 33f14e
  signal (SIGBUS, exception_handler);
Packit 33f14e
#endif
Packit 33f14e
}
Packit 33f14e
#endif
Packit 33f14e
]])