X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/3d9156a7a519a5e3aa1b92e9d9d4b991f1aed7ff..6dccf0e0b5e80b7b6176e8d332e646175431bb3d:/stdlib/FreeBSD/abort.c diff --git a/stdlib/FreeBSD/abort.c b/stdlib/FreeBSD/abort.c index 18d0c73..8758cf8 100644 --- a/stdlib/FreeBSD/abort.c +++ b/stdlib/FreeBSD/abort.c @@ -10,10 +10,6 @@ * 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. @@ -31,27 +27,43 @@ * 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 */ #include -__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.9 2003/08/16 11:43:57 davidxu Exp $"); +__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp Exp $"); #include "namespace.h" #include +#include #include #include #include #include +#include #include "un-namespace.h" -void (*__cleanup)(); +#include "libc_private.h" + +#include +#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. @@ -65,19 +77,85 @@ abort() * 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); + + /* 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); + + /* 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)_sigaction(SIGABRT, &act, NULL); sigdelset(&act.sa_mask, SIGABRT); + + /* 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); + + /* 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: + * 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)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