File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libiconv / srcm4 / nocrash.m4
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 13:38:46 2021 UTC (3 years, 9 months ago) by misho
Branches: libiconv, MAIN
CVS tags: v1_16p0, HEAD
libiconv 1.16

    1: # nocrash.m4 serial 5
    2: dnl Copyright (C) 2005, 2009-2019 Free Software Foundation, Inc.
    3: dnl This file is free software; the Free Software Foundation
    4: dnl gives unlimited permission to copy and/or distribute it,
    5: dnl with or without modifications, as long as this notice is preserved.
    6: 
    7: dnl Based on libsigsegv, from Bruno Haible and Paolo Bonzini.
    8: 
    9: AC_PREREQ([2.13])
   10: 
   11: dnl Expands to some code for use in .c programs that will cause the configure
   12: dnl test to exit instead of crashing. This is useful to avoid triggering
   13: dnl action from a background debugger and to avoid core dumps.
   14: dnl Usage:   ...
   15: dnl          ]GL_NOCRASH[
   16: dnl          ...
   17: dnl          int main() { nocrash_init(); ... }
   18: AC_DEFUN([GL_NOCRASH],[[
   19: #include <stdlib.h>
   20: #if defined __MACH__ && defined __APPLE__
   21: /* Avoid a crash on Mac OS X.  */
   22: #include <mach/mach.h>
   23: #include <mach/mach_error.h>
   24: #include <mach/thread_status.h>
   25: #include <mach/exception.h>
   26: #include <mach/task.h>
   27: #include <pthread.h>
   28: /* The exception port on which our thread listens.  */
   29: static mach_port_t our_exception_port;
   30: /* The main function of the thread listening for exceptions of type
   31:    EXC_BAD_ACCESS.  */
   32: static void *
   33: mach_exception_thread (void *arg)
   34: {
   35:   /* Buffer for a message to be received.  */
   36:   struct {
   37:     mach_msg_header_t head;
   38:     mach_msg_body_t msgh_body;
   39:     char data[1024];
   40:   } msg;
   41:   mach_msg_return_t retval;
   42:   /* Wait for a message on the exception port.  */
   43:   retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
   44:                      our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
   45:   if (retval != MACH_MSG_SUCCESS)
   46:     abort ();
   47:   exit (1);
   48: }
   49: static void
   50: nocrash_init (void)
   51: {
   52:   mach_port_t self = mach_task_self ();
   53:   /* Allocate a port on which the thread shall listen for exceptions.  */
   54:   if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
   55:       == KERN_SUCCESS) {
   56:     /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
   57:     if (mach_port_insert_right (self, our_exception_port, our_exception_port,
   58:                                 MACH_MSG_TYPE_MAKE_SEND)
   59:         == KERN_SUCCESS) {
   60:       /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
   61:          for us.  */
   62:       exception_mask_t mask = EXC_MASK_BAD_ACCESS;
   63:       /* Create the thread listening on the exception port.  */
   64:       pthread_attr_t attr;
   65:       pthread_t thread;
   66:       if (pthread_attr_init (&attr) == 0
   67:           && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
   68:           && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
   69:         pthread_attr_destroy (&attr);
   70:         /* Replace the exception port info for these exceptions with our own.
   71:            Note that we replace the exception port for the entire task, not only
   72:            for a particular thread.  This has the effect that when our exception
   73:            port gets the message, the thread specific exception port has already
   74:            been asked, and we don't need to bother about it.
   75:            See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
   76:         task_set_exception_ports (self, mask, our_exception_port,
   77:                                   EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
   78:       }
   79:     }
   80:   }
   81: }
   82: #elif defined _WIN32 && ! defined __CYGWIN__
   83: /* Avoid a crash on native Windows.  */
   84: #define WIN32_LEAN_AND_MEAN
   85: #include <windows.h>
   86: #include <winerror.h>
   87: static LONG WINAPI
   88: exception_filter (EXCEPTION_POINTERS *ExceptionInfo)
   89: {
   90:   switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
   91:     {
   92:     case EXCEPTION_ACCESS_VIOLATION:
   93:     case EXCEPTION_IN_PAGE_ERROR:
   94:     case EXCEPTION_STACK_OVERFLOW:
   95:     case EXCEPTION_GUARD_PAGE:
   96:     case EXCEPTION_PRIV_INSTRUCTION:
   97:     case EXCEPTION_ILLEGAL_INSTRUCTION:
   98:     case EXCEPTION_DATATYPE_MISALIGNMENT:
   99:     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
  100:     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
  101:       exit (1);
  102:     }
  103:   return EXCEPTION_CONTINUE_SEARCH;
  104: }
  105: static void
  106: nocrash_init (void)
  107: {
  108:   SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) exception_filter);
  109: }
  110: #else
  111: /* Avoid a crash on POSIX systems.  */
  112: #include <signal.h>
  113: #include <unistd.h>
  114: /* A POSIX signal handler.  */
  115: static void
  116: exception_handler (int sig)
  117: {
  118:   _exit (1);
  119: }
  120: static void
  121: nocrash_init (void)
  122: {
  123: #ifdef SIGSEGV
  124:   signal (SIGSEGV, exception_handler);
  125: #endif
  126: #ifdef SIGBUS
  127:   signal (SIGBUS, exception_handler);
  128: #endif
  129: }
  130: #endif
  131: ]])

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>