1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "lint.h"
28 #include "thr_uberdata.h"
29
30 const char *panicstr;
31 ulwp_t *panic_thread;
32
33 static mutex_t assert_lock = DEFAULTMUTEX;
34 static ulwp_t *assert_thread = NULL;
35
36 /*
37 * Called from __assert() to set panicstr and panic_thread.
38 */
39 void
__set_panicstr(const char * msg)40 __set_panicstr(const char *msg)
41 {
42 panicstr = msg;
43 panic_thread = __curthread();
44 }
45
46 /*
47 * Called from exit() (atexit function) to give precedence
48 * to assertion failures and a core dump over _exit().
49 */
50 void
grab_assert_lock()51 grab_assert_lock()
52 {
53 (void) _lwp_mutex_lock(&assert_lock);
54 }
55
56 static void
Abort(const char * msg)57 Abort(const char *msg)
58 {
59 ulwp_t *self;
60 struct sigaction act;
61 sigset_t sigmask;
62 lwpid_t lwpid;
63
64 /* to help with core file debugging */
65 panicstr = msg;
66 if ((self = __curthread()) != NULL) {
67 panic_thread = self;
68 lwpid = self->ul_lwpid;
69 } else {
70 lwpid = _lwp_self();
71 }
72
73 /* set SIGABRT signal handler to SIG_DFL w/o grabbing any locks */
74 (void) memset(&act, 0, sizeof (act));
75 act.sa_sigaction = SIG_DFL;
76 (void) __sigaction(SIGABRT, &act, NULL);
77
78 /* delete SIGABRT from the signal mask */
79 (void) sigemptyset(&sigmask);
80 (void) sigaddset(&sigmask, SIGABRT);
81 (void) __lwp_sigmask(SIG_UNBLOCK, &sigmask);
82
83 (void) _lwp_kill(lwpid, SIGABRT); /* never returns */
84 (void) kill(getpid(), SIGABRT); /* if it does, try harder */
85 _exit(127);
86 }
87
88 /*
89 * Write a panic message w/o grabbing any locks other than assert_lock.
90 * We have no idea what locks are held at this point.
91 */
92 static void
common_panic(const char * head,const char * why)93 common_panic(const char *head, const char *why)
94 {
95 char msg[400]; /* no panic() message in the library is this long */
96 ulwp_t *self;
97 size_t len1, len2;
98
99 if ((self = __curthread()) != NULL)
100 enter_critical(self);
101 (void) _lwp_mutex_lock(&assert_lock);
102
103 (void) memset(msg, 0, sizeof (msg));
104 (void) strcpy(msg, head);
105 len1 = strlen(msg);
106 len2 = strlen(why);
107 if (len1 + len2 >= sizeof (msg))
108 len2 = sizeof (msg) - len1 - 1;
109 (void) strncat(msg, why, len2);
110 len1 = strlen(msg);
111 if (msg[len1 - 1] != '\n')
112 msg[len1++] = '\n';
113 (void) __write(2, msg, len1);
114 Abort(msg);
115 }
116
117 void
thr_panic(const char * why)118 thr_panic(const char *why)
119 {
120 common_panic("*** libc thread failure: ", why);
121 }
122
123 void
aio_panic(const char * why)124 aio_panic(const char *why)
125 {
126 common_panic("*** libc aio system failure: ", why);
127 }
128
129 /*
130 * Utility function for converting a long integer to a string, avoiding stdio.
131 * 'base' must be one of 10 or 16
132 */
133 void
ultos(uint64_t n,int base,char * s)134 ultos(uint64_t n, int base, char *s)
135 {
136 char lbuf[24]; /* 64 bits fits in 16 hex digits, 20 decimal */
137 char *cp = lbuf;
138
139 do {
140 *cp++ = "0123456789abcdef"[n%base];
141 n /= base;
142 } while (n);
143 if (base == 16) {
144 *s++ = '0';
145 *s++ = 'x';
146 }
147 do {
148 *s++ = *--cp;
149 } while (cp > lbuf);
150 *s = '\0';
151 }
152
153 /*
154 * Report application lock usage error for mutexes and condvars.
155 * Not called if _THREAD_ERROR_DETECTION=0.
156 * Continue execution if _THREAD_ERROR_DETECTION=1.
157 * Dump core if _THREAD_ERROR_DETECTION=2.
158 */
159 void
lock_error(const mutex_t * mp,const char * who,void * cv,const char * msg)160 lock_error(const mutex_t *mp, const char *who, void *cv, const char *msg)
161 {
162 mutex_t mcopy;
163 char buf[800];
164 uberdata_t *udp;
165 ulwp_t *self;
166 lwpid_t lwpid;
167 pid_t pid;
168
169 /*
170 * Take a snapshot of the mutex before it changes (we hope!).
171 * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
172 */
173 (void) memcpy(&mcopy, mp, sizeof (mcopy));
174
175 /* avoid recursion deadlock */
176 if ((self = __curthread()) != NULL) {
177 if (assert_thread == self)
178 _exit(127);
179 enter_critical(self);
180 (void) _lwp_mutex_lock(&assert_lock);
181 assert_thread = self;
182 lwpid = self->ul_lwpid;
183 udp = self->ul_uberdata;
184 pid = udp->pid;
185 } else {
186 self = NULL;
187 (void) _lwp_mutex_lock(&assert_lock);
188 lwpid = _lwp_self();
189 udp = &__uberdata;
190 pid = getpid();
191 }
192
193 (void) strcpy(buf,
194 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
195 (void) strcat(buf, who);
196 (void) strcat(buf, "(");
197 if (cv != NULL) {
198 ultos((uint64_t)(uintptr_t)cv, 16, buf + strlen(buf));
199 (void) strcat(buf, ", ");
200 }
201 ultos((uint64_t)(uintptr_t)mp, 16, buf + strlen(buf));
202 (void) strcat(buf, ")");
203 if (msg != NULL) {
204 (void) strcat(buf, ": ");
205 (void) strcat(buf, msg);
206 } else if (!mutex_held(&mcopy)) {
207 (void) strcat(buf, ": calling thread does not own the lock");
208 } else if (mcopy.mutex_rcount) {
209 (void) strcat(buf, ": mutex rcount = ");
210 ultos((uint64_t)mcopy.mutex_rcount, 10, buf + strlen(buf));
211 } else {
212 (void) strcat(buf, ": calling thread already owns the lock");
213 }
214 (void) strcat(buf, "\ncalling thread is ");
215 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
216 (void) strcat(buf, " thread-id ");
217 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
218 if (msg != NULL || mutex_held(&mcopy))
219 /* EMPTY */;
220 else if (mcopy.mutex_lockw == 0)
221 (void) strcat(buf, "\nthe lock is unowned");
222 else if (!(mcopy.mutex_type & USYNC_PROCESS)) {
223 (void) strcat(buf, "\nthe lock owner is ");
224 ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
225 } else {
226 (void) strcat(buf, " in process ");
227 ultos((uint64_t)pid, 10, buf + strlen(buf));
228 (void) strcat(buf, "\nthe lock owner is ");
229 ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
230 (void) strcat(buf, " in process ");
231 ultos((uint64_t)mcopy.mutex_ownerpid, 10, buf + strlen(buf));
232 }
233 (void) strcat(buf, "\n\n");
234 (void) __write(2, buf, strlen(buf));
235 if (udp->uberflags.uf_thread_error_detection >= 2)
236 Abort(buf);
237 assert_thread = NULL;
238 (void) _lwp_mutex_unlock(&assert_lock);
239 if (self != NULL)
240 exit_critical(self);
241 }
242
243 /*
244 * Report application lock usage error for rwlocks.
245 * Not called if _THREAD_ERROR_DETECTION=0.
246 * Continue execution if _THREAD_ERROR_DETECTION=1.
247 * Dump core if _THREAD_ERROR_DETECTION=2.
248 */
249 void
rwlock_error(const rwlock_t * rp,const char * who,const char * msg)250 rwlock_error(const rwlock_t *rp, const char *who, const char *msg)
251 {
252 rwlock_t rcopy;
253 uint32_t rwstate;
254 char buf[800];
255 uberdata_t *udp;
256 ulwp_t *self;
257 lwpid_t lwpid;
258 pid_t pid;
259 int process;
260
261 /*
262 * Take a snapshot of the rwlock before it changes (we hope!).
263 * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
264 */
265 (void) memcpy(&rcopy, rp, sizeof (rcopy));
266
267 /* avoid recursion deadlock */
268 if ((self = __curthread()) != NULL) {
269 if (assert_thread == self)
270 _exit(127);
271 enter_critical(self);
272 (void) _lwp_mutex_lock(&assert_lock);
273 assert_thread = self;
274 lwpid = self->ul_lwpid;
275 udp = self->ul_uberdata;
276 pid = udp->pid;
277 } else {
278 self = NULL;
279 (void) _lwp_mutex_lock(&assert_lock);
280 lwpid = _lwp_self();
281 udp = &__uberdata;
282 pid = getpid();
283 }
284
285 rwstate = (uint32_t)rcopy.rwlock_readers;
286 process = (rcopy.rwlock_type & USYNC_PROCESS);
287
288 (void) strcpy(buf,
289 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
290 (void) strcat(buf, who);
291 (void) strcat(buf, "(");
292 ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf));
293 (void) strcat(buf, "): ");
294 (void) strcat(buf, msg);
295 (void) strcat(buf, "\ncalling thread is ");
296 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
297 (void) strcat(buf, " thread-id ");
298 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
299 if (process) {
300 (void) strcat(buf, " in process ");
301 ultos((uint64_t)pid, 10, buf + strlen(buf));
302 }
303 if (rwstate & URW_WRITE_LOCKED) {
304 (void) strcat(buf, "\nthe writer lock owner is ");
305 ultos((uint64_t)rcopy.rwlock_owner, 16,
306 buf + strlen(buf));
307 if (process) {
308 (void) strcat(buf, " in process ");
309 ultos((uint64_t)rcopy.rwlock_ownerpid, 10,
310 buf + strlen(buf));
311 }
312 } else if (rwstate & URW_READERS_MASK) {
313 (void) strcat(buf, "\nthe reader lock is held by ");
314 ultos((uint64_t)(rwstate & URW_READERS_MASK), 10,
315 buf + strlen(buf));
316 (void) strcat(buf, " readers");
317 } else {
318 (void) strcat(buf, "\nthe lock is unowned");
319 }
320 if (rwstate & URW_HAS_WAITERS)
321 (void) strcat(buf, "\nand the lock appears to have waiters");
322 (void) strcat(buf, "\n\n");
323 (void) __write(2, buf, strlen(buf));
324 if (udp->uberflags.uf_thread_error_detection >= 2)
325 Abort(buf);
326 assert_thread = NULL;
327 (void) _lwp_mutex_unlock(&assert_lock);
328 if (self != NULL)
329 exit_critical(self);
330 }
331
332 /*
333 * Report a thread usage error.
334 * Not called if _THREAD_ERROR_DETECTION=0.
335 * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
336 * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
337 */
338 void
thread_error(const char * msg)339 thread_error(const char *msg)
340 {
341 char buf[800];
342 uberdata_t *udp;
343 ulwp_t *self;
344 lwpid_t lwpid;
345
346 /* avoid recursion deadlock */
347 if ((self = __curthread()) != NULL) {
348 if (assert_thread == self)
349 _exit(127);
350 enter_critical(self);
351 (void) _lwp_mutex_lock(&assert_lock);
352 assert_thread = self;
353 lwpid = self->ul_lwpid;
354 udp = self->ul_uberdata;
355 } else {
356 self = NULL;
357 (void) _lwp_mutex_lock(&assert_lock);
358 lwpid = _lwp_self();
359 udp = &__uberdata;
360 }
361
362 (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: "
363 "thread usage error detected ***\n*** ");
364 (void) strcat(buf, msg);
365
366 (void) strcat(buf, "\n*** calling thread is ");
367 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
368 (void) strcat(buf, " thread-id ");
369 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
370 (void) strcat(buf, "\n\n");
371 (void) __write(2, buf, strlen(buf));
372 if (udp->uberflags.uf_thread_error_detection >= 2)
373 Abort(buf);
374 assert_thread = NULL;
375 (void) _lwp_mutex_unlock(&assert_lock);
376 if (self != NULL)
377 exit_critical(self);
378 }
379
380 /*
381 * We use __assfail() because the libc __assert() calls
382 * gettext() which calls malloc() which grabs a mutex.
383 * We do everything without calling standard i/o.
384 * assfail() and _assfail() are exported functions;
385 * __assfail() is private to libc.
386 */
387 #pragma weak _assfail = __assfail
388 void
__assfail(const char * assertion,const char * filename,int line_num)389 __assfail(const char *assertion, const char *filename, int line_num)
390 {
391 char buf[800]; /* no assert() message in the library is this long */
392 ulwp_t *self;
393 lwpid_t lwpid;
394
395 /* avoid recursion deadlock */
396 if ((self = __curthread()) != NULL) {
397 if (assert_thread == self)
398 _exit(127);
399 enter_critical(self);
400 (void) _lwp_mutex_lock(&assert_lock);
401 assert_thread = self;
402 lwpid = self->ul_lwpid;
403 } else {
404 self = NULL;
405 (void) _lwp_mutex_lock(&assert_lock);
406 lwpid = _lwp_self();
407 }
408
409 (void) strcpy(buf, "assertion failed for thread ");
410 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
411 (void) strcat(buf, ", thread-id ");
412 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
413 (void) strcat(buf, ": ");
414 (void) strcat(buf, assertion);
415 (void) strcat(buf, ", file ");
416 (void) strcat(buf, filename);
417 (void) strcat(buf, ", line ");
418 ultos((uint64_t)line_num, 10, buf + strlen(buf));
419 (void) strcat(buf, "\n");
420 (void) __write(2, buf, strlen(buf));
421 /*
422 * We could replace the call to Abort() with the following code
423 * if we want just to issue a warning message and not die.
424 * assert_thread = NULL;
425 * _lwp_mutex_unlock(&assert_lock);
426 * if (self != NULL)
427 * exit_critical(self);
428 */
429 Abort(buf);
430 }
431
432 /*
433 * We define and export this version of assfail() just because libaio
434 * used to define and export it, needlessly. Now that libaio is folded
435 * into libc, we need to continue this for ABI/version reasons.
436 * We don't use "#pragma weak assfail __assfail" in order to avoid
437 * warnings from the check_fnames utility at build time for libraries
438 * that define their own version of assfail().
439 */
440 void
assfail(const char * assertion,const char * filename,int line_num)441 assfail(const char *assertion, const char *filename, int line_num)
442 {
443 __assfail(assertion, filename, line_num);
444 }
445