]> git.saurik.com Git - apple/libc.git/blob - stdlib/FreeBSD/abort.c.patch
bb724175f91235265bfcccac0bf4fbf1b95d3ee5
[apple/libc.git] / stdlib / FreeBSD / abort.c.patch
1 --- abort.c.orig 2010-09-07 22:42:56.000000000 -0700
2 +++ abort.c 2010-09-07 22:46:29.000000000 -0700
3 @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
4
5 #include "namespace.h"
6 #include <signal.h>
7 +#include <stdarg.h>
8 #include <stdlib.h>
9 #include <stddef.h>
10 #include <unistd.h>
11 @@ -43,11 +44,22 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
12
13 #include "libc_private.h"
14
15 +#include "CrashReporterClient.h"
16 +#include "_simple.h"
17 +
18 +extern void (*__cleanup)();
19 +extern void __abort(void) __dead2;
20 +
21 +#define TIMEOUT 10000 /* 10 milliseconds */
22 +
23 void
24 abort()
25 {
26 struct sigaction act;
27
28 + if (!CRGetCrashLogMessage())
29 + CRSetCrashLogMessage("abort() called");
30 +
31 /*
32 * POSIX requires we flush stdio buffers on abort.
33 * XXX ISO C requires that abort() be async-signal-safe.
34 @@ -61,19 +73,90 @@ abort()
35 * any errors -- ISO C doesn't allow abort to return anyway.
36 */
37 sigdelset(&act.sa_mask, SIGABRT);
38 - (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
39 - (void)raise(SIGABRT);
40 +
41 + /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread
42 + * This helps gdb focus on the thread calling abort()
43 + */
44 + if (__is_threaded) {
45 + /* Block all signals on all other threads */
46 + sigset_t fullmask;
47 + sigfillset(&fullmask);
48 + (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
49 +
50 + /* <rdar://problem/8400096> Set the workqueue killable */
51 + __pthread_workqueue_setkill(1);
52 +
53 + (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
54 + (void)pthread_kill(pthread_self(), SIGABRT);
55 + } else {
56 + (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
57 + (void)kill(getpid(), SIGABRT);
58 + }
59 + usleep(TIMEOUT); /* give time for signal to happen */
60
61 /*
62 * If SIGABRT was ignored, or caught and the handler returns, do
63 * it again, only harder.
64 */
65 + __abort();
66 +}
67 +
68 +__private_extern__ void
69 +__abort()
70 +{
71 + struct sigaction act;
72 +
73 + if (!CRGetCrashLogMessage())
74 + CRSetCrashLogMessage("__abort() called");
75 act.sa_handler = SIG_DFL;
76 act.sa_flags = 0;
77 sigfillset(&act.sa_mask);
78 (void)_sigaction(SIGABRT, &act, NULL);
79 sigdelset(&act.sa_mask, SIGABRT);
80 +
81 + /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread
82 + * This helps gdb focus on the thread calling abort()
83 + */
84 + if (__is_threaded) {
85 + /* Block all signals on all other threads */
86 + sigset_t fullmask;
87 + sigfillset(&fullmask);
88 + (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
89 +
90 + /* <rdar://problem/8400096> Set the workqueue killable */
91 + __pthread_workqueue_setkill(1);
92 +
93 + (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
94 + (void)pthread_kill(pthread_self(), SIGABRT);
95 + } else {
96 + (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
97 + (void)kill(getpid(), SIGABRT);
98 + }
99 + usleep(TIMEOUT); /* give time for signal to happen */
100 +
101 + /* If for some reason SIGABRT was not delivered, we exit using __builtin_trap
102 + * which generates an illegal instruction on i386: <rdar://problem/8400958>
103 + * and SIGTRAP on arm.
104 + */
105 + sigfillset(&act.sa_mask);
106 + sigdelset(&act.sa_mask, SIGILL);
107 + sigdelset(&act.sa_mask, SIGTRAP);
108 (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
109 - (void)raise(SIGABRT);
110 - exit(1);
111 + __builtin_trap();
112 +}
113 +
114 +__private_extern__ void
115 +abort_report_np(const char *fmt, ...)
116 +{
117 + _SIMPLE_STRING s;
118 + va_list ap;
119 +
120 + if ((s = _simple_salloc()) != NULL) {
121 + va_start(ap, fmt);
122 + _simple_vsprintf(s, fmt, ap);
123 + va_end(ap);
124 + CRSetCrashLogMessage(_simple_string(s));
125 + } else
126 + CRSetCrashLogMessage(fmt); /* the format string is better than nothing */
127 + abort();
128 }