]> git.saurik.com Git - apple/libc.git/blobdiff - stdlib/FreeBSD/abort.c
Libc-1272.250.1.tar.gz
[apple/libc.git] / stdlib / FreeBSD / abort.c
index 50e34b00916c59f2520a11a044cfe5519189d2d9..8758cf885f34b1565bfb814760cca360a30e7744 100644 (file)
@@ -27,6 +27,9 @@
  * SUCH DAMAGE.
  */
 
  * SUCH DAMAGE.
  */
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wstrict-prototypes"
+
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)abort.c    8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)abort.c    8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
@@ -35,19 +38,32 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp E
 
 #include "namespace.h"
 #include <signal.h>
 
 #include "namespace.h"
 #include <signal.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <pthread_workqueue.h>
 #include "un-namespace.h"
 
 #include "libc_private.h"
 
 #include "un-namespace.h"
 
 #include "libc_private.h"
 
+#include <CrashReporterClient.h>
+#include "_simple.h"
+
+extern void (*__cleanup)();
+extern void __abort(void) __dead2;
+
+#define TIMEOUT        10000   /* 10 milliseconds */
+
 void
 abort()
 {
        struct sigaction act;
 
 void
 abort()
 {
        struct sigaction act;
 
+       if (!CRGetCrashLogMessage())
+               CRSetCrashLogMessage("abort() called");
+
        /*
         * POSIX requires we flush stdio buffers on abort.
         * XXX ISO C requires that abort() be async-signal-safe.
        /*
         * POSIX requires we flush stdio buffers on abort.
         * XXX ISO C requires that abort() be async-signal-safe.
@@ -61,19 +77,85 @@ abort()
         * any errors -- ISO C doesn't allow abort to return anyway.
         */
        sigdelset(&act.sa_mask, SIGABRT);
         * any errors -- ISO C doesn't allow abort to return anyway.
         */
        sigdelset(&act.sa_mask, SIGABRT);
-       (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
-       (void)raise(SIGABRT);
+
+       /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread 
+        * This helps gdb focus on the thread calling abort()
+        */
+
+       /* Block all signals on all other threads */
+       sigset_t fullmask;
+       sigfillset(&fullmask);
+       (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
+
+       /* <rdar://problem/8400096> Set the workqueue killable */
+       __pthread_workqueue_setkill(1);
+
+       (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
+       (void)pthread_kill(pthread_self(), SIGABRT);
+
+       usleep(TIMEOUT); /* give time for signal to happen */
 
        /*
         * If SIGABRT was ignored, or caught and the handler returns, do
         * it again, only harder.
         */
 
        /*
         * If SIGABRT was ignored, or caught and the handler returns, do
         * it again, only harder.
         */
+        __abort();
+}
+
+__private_extern__ void
+__abort()
+{
+       struct sigaction act;
+
+       if (!CRGetCrashLogMessage())
+               CRSetCrashLogMessage("__abort() called");
        act.sa_handler = SIG_DFL;
        act.sa_flags = 0;
        sigfillset(&act.sa_mask);
        (void)_sigaction(SIGABRT, &act, NULL);
        sigdelset(&act.sa_mask, SIGABRT);
        act.sa_handler = SIG_DFL;
        act.sa_flags = 0;
        sigfillset(&act.sa_mask);
        (void)_sigaction(SIGABRT, &act, NULL);
        sigdelset(&act.sa_mask, SIGABRT);
+
+       /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread 
+        * This helps gdb focus on the thread calling abort()
+        */
+
+       /* Block all signals on all other threads */
+       sigset_t fullmask;
+       sigfillset(&fullmask);
+       (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
+
+       /* <rdar://problem/8400096> Set the workqueue killable */
+       __pthread_workqueue_setkill(1);
+
+       (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
+       (void)pthread_kill(pthread_self(), SIGABRT);
+
+       usleep(TIMEOUT); /* give time for signal to happen */
+
+       /* If for some reason SIGABRT was not delivered, we exit using __builtin_trap
+        * which generates an illegal instruction on i386: <rdar://problem/8400958>
+        * and SIGTRAP on arm.
+        */
+       sigfillset(&act.sa_mask);
+       sigdelset(&act.sa_mask, SIGILL);
+       sigdelset(&act.sa_mask, SIGTRAP);
        (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
        (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
-       (void)raise(SIGABRT);
-       exit(1);
+       __builtin_trap();
+}
+
+void
+abort_report_np(const char *fmt, ...)
+{
+       _SIMPLE_STRING s;
+       va_list ap;
+
+       if ((s = _simple_salloc()) != NULL) {
+               va_start(ap, fmt);
+               _simple_vsprintf(s, fmt, ap);
+               va_end(ap);
+               CRSetCrashLogMessage(_simple_string(s));
+       } else
+               CRSetCrashLogMessage(fmt); /* the format string is better than nothing */
+       abort();
 }
 }
+#pragma clang diagnostic pop