Blame m4/nocrash.m4

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