]> git.saurik.com Git - apple/libc.git/blobdiff - stdlib/FreeBSD/abort.c
Libc-1158.50.2.tar.gz
[apple/libc.git] / stdlib / FreeBSD / abort.c
index 28acb306ce81cf5601c253d67d5beaaa7251e7d6..386572c4d429e1cbf5c5120785ff42e649b2aeb5 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
 static char sccsid[] = "@(#)abort.c    8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.8 2002/07/10 16:35:02 wollman Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp Exp $");
 
+#include "namespace.h"
 #include <signal.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <pthread_workqueue.h>
+#include "un-namespace.h"
 
-void (*__cleanup)();
+#include "libc_private.h"
 
-/* XXX - why are these declarations here? */
-extern int     __sys_sigprocmask(int, const sigset_t *, sigset_t *);
-extern int     __sys_sigaction(int, const struct sigaction *,
-                   struct sigaction *);
+#include <CrashReporterClient.h>
+#include "_simple.h"
+
+extern void (*__cleanup)();
+extern void __abort(void) __dead2;
+
+#define TIMEOUT        10000   /* 10 milliseconds */
 
 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.
@@ -68,19 +74,84 @@ abort()
         * any errors -- ISO C doesn't allow abort to return anyway.
         */
        sigdelset(&act.sa_mask, SIGABRT);
-       (void)__sys_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
-       (void)kill(getpid(), 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.
         */
+        __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)__sys_sigaction(SIGABRT, &act, NULL);
+       (void)_sigaction(SIGABRT, &act, NULL);
        sigdelset(&act.sa_mask, SIGABRT);
-       (void)__sys_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
-       (void)kill(getpid(), SIGABRT);
-       exit(1);
+
+       /* <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);
+       __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();
 }