Blame m4/nocrash.m4

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