5815 libzpool's panic function doesn't set global panicstr, ::status not as useful
[unleashed.git] / usr / src / lib / libc / port / threads / assfail.c
blob8aebefbe4ac7a1ede9eba8bbf7392201673a0df2
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
30 #include "lint.h"
31 #include "thr_uberdata.h"
33 const char *panicstr;
34 ulwp_t *panic_thread;
36 static mutex_t assert_lock = DEFAULTMUTEX;
37 static ulwp_t *assert_thread = NULL;
40 * Called from __assert() to set panicstr and panic_thread.
42 void
43 __set_panicstr(const char *msg)
45 panicstr = msg;
46 panic_thread = __curthread();
50 * Called from exit() (atexit function) to give precedence
51 * to assertion failures and a core dump over _exit().
53 void
54 grab_assert_lock()
56 (void) _lwp_mutex_lock(&assert_lock);
59 static void
60 Abort(const char *msg)
62 ulwp_t *self;
63 struct sigaction act;
64 sigset_t sigmask;
65 lwpid_t lwpid;
67 /* to help with core file debugging */
68 panicstr = msg;
69 if ((self = __curthread()) != NULL) {
70 panic_thread = self;
71 lwpid = self->ul_lwpid;
72 } else {
73 lwpid = _lwp_self();
76 /* set SIGABRT signal handler to SIG_DFL w/o grabbing any locks */
77 (void) memset(&act, 0, sizeof (act));
78 act.sa_sigaction = SIG_DFL;
79 (void) __sigaction(SIGABRT, &act, NULL);
81 /* delete SIGABRT from the signal mask */
82 (void) sigemptyset(&sigmask);
83 (void) sigaddset(&sigmask, SIGABRT);
84 (void) __lwp_sigmask(SIG_UNBLOCK, &sigmask);
86 (void) _lwp_kill(lwpid, SIGABRT); /* never returns */
87 (void) kill(getpid(), SIGABRT); /* if it does, try harder */
88 _exit(127);
92 * Write a panic message w/o grabbing any locks other than assert_lock.
93 * We have no idea what locks are held at this point.
95 static void
96 common_panic(const char *head, const char *why)
98 char msg[400]; /* no panic() message in the library is this long */
99 ulwp_t *self;
100 size_t len1, len2;
102 if ((self = __curthread()) != NULL)
103 enter_critical(self);
104 (void) _lwp_mutex_lock(&assert_lock);
106 (void) memset(msg, 0, sizeof (msg));
107 (void) strcpy(msg, head);
108 len1 = strlen(msg);
109 len2 = strlen(why);
110 if (len1 + len2 >= sizeof (msg))
111 len2 = sizeof (msg) - len1 - 1;
112 (void) strncat(msg, why, len2);
113 len1 = strlen(msg);
114 if (msg[len1 - 1] != '\n')
115 msg[len1++] = '\n';
116 (void) __write(2, msg, len1);
117 Abort(msg);
120 void
121 thr_panic(const char *why)
123 common_panic("*** libc thread failure: ", why);
126 void
127 aio_panic(const char *why)
129 common_panic("*** libc aio system failure: ", why);
133 * Utility function for converting a long integer to a string, avoiding stdio.
134 * 'base' must be one of 10 or 16
136 void
137 ultos(uint64_t n, int base, char *s)
139 char lbuf[24]; /* 64 bits fits in 16 hex digits, 20 decimal */
140 char *cp = lbuf;
142 do {
143 *cp++ = "0123456789abcdef"[n%base];
144 n /= base;
145 } while (n);
146 if (base == 16) {
147 *s++ = '0';
148 *s++ = 'x';
150 do {
151 *s++ = *--cp;
152 } while (cp > lbuf);
153 *s = '\0';
157 * Report application lock usage error for mutexes and condvars.
158 * Not called if _THREAD_ERROR_DETECTION=0.
159 * Continue execution if _THREAD_ERROR_DETECTION=1.
160 * Dump core if _THREAD_ERROR_DETECTION=2.
162 void
163 lock_error(const mutex_t *mp, const char *who, void *cv, const char *msg)
165 mutex_t mcopy;
166 char buf[800];
167 uberdata_t *udp;
168 ulwp_t *self;
169 lwpid_t lwpid;
170 pid_t pid;
173 * Take a snapshot of the mutex before it changes (we hope!).
174 * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
176 (void) memcpy(&mcopy, mp, sizeof (mcopy));
178 /* avoid recursion deadlock */
179 if ((self = __curthread()) != NULL) {
180 if (assert_thread == self)
181 _exit(127);
182 enter_critical(self);
183 (void) _lwp_mutex_lock(&assert_lock);
184 assert_thread = self;
185 lwpid = self->ul_lwpid;
186 udp = self->ul_uberdata;
187 pid = udp->pid;
188 } else {
189 self = NULL;
190 (void) _lwp_mutex_lock(&assert_lock);
191 lwpid = _lwp_self();
192 udp = &__uberdata;
193 pid = getpid();
196 (void) strcpy(buf,
197 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
198 (void) strcat(buf, who);
199 (void) strcat(buf, "(");
200 if (cv != NULL) {
201 ultos((uint64_t)(uintptr_t)cv, 16, buf + strlen(buf));
202 (void) strcat(buf, ", ");
204 ultos((uint64_t)(uintptr_t)mp, 16, buf + strlen(buf));
205 (void) strcat(buf, ")");
206 if (msg != NULL) {
207 (void) strcat(buf, ": ");
208 (void) strcat(buf, msg);
209 } else if (!mutex_held(&mcopy)) {
210 (void) strcat(buf, ": calling thread does not own the lock");
211 } else if (mcopy.mutex_rcount) {
212 (void) strcat(buf, ": mutex rcount = ");
213 ultos((uint64_t)mcopy.mutex_rcount, 10, buf + strlen(buf));
214 } else {
215 (void) strcat(buf, ": calling thread already owns the lock");
217 (void) strcat(buf, "\ncalling thread is ");
218 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
219 (void) strcat(buf, " thread-id ");
220 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
221 if (msg != NULL || mutex_held(&mcopy))
222 /* EMPTY */;
223 else if (mcopy.mutex_lockw == 0)
224 (void) strcat(buf, "\nthe lock is unowned");
225 else if (!(mcopy.mutex_type & USYNC_PROCESS)) {
226 (void) strcat(buf, "\nthe lock owner is ");
227 ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
228 } else {
229 (void) strcat(buf, " in process ");
230 ultos((uint64_t)pid, 10, buf + strlen(buf));
231 (void) strcat(buf, "\nthe lock owner is ");
232 ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
233 (void) strcat(buf, " in process ");
234 ultos((uint64_t)mcopy.mutex_ownerpid, 10, buf + strlen(buf));
236 (void) strcat(buf, "\n\n");
237 (void) __write(2, buf, strlen(buf));
238 if (udp->uberflags.uf_thread_error_detection >= 2)
239 Abort(buf);
240 assert_thread = NULL;
241 (void) _lwp_mutex_unlock(&assert_lock);
242 if (self != NULL)
243 exit_critical(self);
247 * Report application lock usage error for rwlocks.
248 * Not called if _THREAD_ERROR_DETECTION=0.
249 * Continue execution if _THREAD_ERROR_DETECTION=1.
250 * Dump core if _THREAD_ERROR_DETECTION=2.
252 void
253 rwlock_error(const rwlock_t *rp, const char *who, const char *msg)
255 rwlock_t rcopy;
256 uint32_t rwstate;
257 char buf[800];
258 uberdata_t *udp;
259 ulwp_t *self;
260 lwpid_t lwpid;
261 pid_t pid;
262 int process;
265 * Take a snapshot of the rwlock before it changes (we hope!).
266 * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
268 (void) memcpy(&rcopy, rp, sizeof (rcopy));
270 /* avoid recursion deadlock */
271 if ((self = __curthread()) != NULL) {
272 if (assert_thread == self)
273 _exit(127);
274 enter_critical(self);
275 (void) _lwp_mutex_lock(&assert_lock);
276 assert_thread = self;
277 lwpid = self->ul_lwpid;
278 udp = self->ul_uberdata;
279 pid = udp->pid;
280 } else {
281 self = NULL;
282 (void) _lwp_mutex_lock(&assert_lock);
283 lwpid = _lwp_self();
284 udp = &__uberdata;
285 pid = getpid();
288 rwstate = (uint32_t)rcopy.rwlock_readers;
289 process = (rcopy.rwlock_type & USYNC_PROCESS);
291 (void) strcpy(buf,
292 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
293 (void) strcat(buf, who);
294 (void) strcat(buf, "(");
295 ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf));
296 (void) strcat(buf, "): ");
297 (void) strcat(buf, msg);
298 (void) strcat(buf, "\ncalling thread is ");
299 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
300 (void) strcat(buf, " thread-id ");
301 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
302 if (process) {
303 (void) strcat(buf, " in process ");
304 ultos((uint64_t)pid, 10, buf + strlen(buf));
306 if (rwstate & URW_WRITE_LOCKED) {
307 (void) strcat(buf, "\nthe writer lock owner is ");
308 ultos((uint64_t)rcopy.rwlock_owner, 16,
309 buf + strlen(buf));
310 if (process) {
311 (void) strcat(buf, " in process ");
312 ultos((uint64_t)rcopy.rwlock_ownerpid, 10,
313 buf + strlen(buf));
315 } else if (rwstate & URW_READERS_MASK) {
316 (void) strcat(buf, "\nthe reader lock is held by ");
317 ultos((uint64_t)(rwstate & URW_READERS_MASK), 10,
318 buf + strlen(buf));
319 (void) strcat(buf, " readers");
320 } else {
321 (void) strcat(buf, "\nthe lock is unowned");
323 if (rwstate & URW_HAS_WAITERS)
324 (void) strcat(buf, "\nand the lock appears to have waiters");
325 (void) strcat(buf, "\n\n");
326 (void) __write(2, buf, strlen(buf));
327 if (udp->uberflags.uf_thread_error_detection >= 2)
328 Abort(buf);
329 assert_thread = NULL;
330 (void) _lwp_mutex_unlock(&assert_lock);
331 if (self != NULL)
332 exit_critical(self);
336 * Report a thread usage error.
337 * Not called if _THREAD_ERROR_DETECTION=0.
338 * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
339 * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
341 void
342 thread_error(const char *msg)
344 char buf[800];
345 uberdata_t *udp;
346 ulwp_t *self;
347 lwpid_t lwpid;
349 /* avoid recursion deadlock */
350 if ((self = __curthread()) != NULL) {
351 if (assert_thread == self)
352 _exit(127);
353 enter_critical(self);
354 (void) _lwp_mutex_lock(&assert_lock);
355 assert_thread = self;
356 lwpid = self->ul_lwpid;
357 udp = self->ul_uberdata;
358 } else {
359 self = NULL;
360 (void) _lwp_mutex_lock(&assert_lock);
361 lwpid = _lwp_self();
362 udp = &__uberdata;
365 (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: "
366 "thread usage error detected ***\n*** ");
367 (void) strcat(buf, msg);
369 (void) strcat(buf, "\n*** calling thread is ");
370 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
371 (void) strcat(buf, " thread-id ");
372 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
373 (void) strcat(buf, "\n\n");
374 (void) __write(2, buf, strlen(buf));
375 if (udp->uberflags.uf_thread_error_detection >= 2)
376 Abort(buf);
377 assert_thread = NULL;
378 (void) _lwp_mutex_unlock(&assert_lock);
379 if (self != NULL)
380 exit_critical(self);
384 * We use __assfail() because the libc __assert() calls
385 * gettext() which calls malloc() which grabs a mutex.
386 * We do everything without calling standard i/o.
387 * assfail() and _assfail() are exported functions;
388 * __assfail() is private to libc.
390 #pragma weak _assfail = __assfail
391 void
392 __assfail(const char *assertion, const char *filename, int line_num)
394 char buf[800]; /* no assert() message in the library is this long */
395 ulwp_t *self;
396 lwpid_t lwpid;
398 /* avoid recursion deadlock */
399 if ((self = __curthread()) != NULL) {
400 if (assert_thread == self)
401 _exit(127);
402 enter_critical(self);
403 (void) _lwp_mutex_lock(&assert_lock);
404 assert_thread = self;
405 lwpid = self->ul_lwpid;
406 } else {
407 self = NULL;
408 (void) _lwp_mutex_lock(&assert_lock);
409 lwpid = _lwp_self();
413 * This is a hack, but since the Abort function isn't exported
414 * to outside consumers, libzpool's vpanic() function calls
415 * assfail() with a filename set to NULL. In that case, it'd be
416 * best not to print "assertion failed" since it was a panic and
417 * not an assertion failure.
419 if (filename == NULL) {
420 (void) strcpy(buf, "failure for thread ");
421 } else {
422 (void) strcpy(buf, "assertion failed for thread ");
425 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
426 (void) strcat(buf, ", thread-id ");
427 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
428 (void) strcat(buf, ": ");
429 (void) strcat(buf, assertion);
431 if (filename != NULL) {
432 (void) strcat(buf, ", file ");
433 (void) strcat(buf, filename);
434 (void) strcat(buf, ", line ");
435 ultos((uint64_t)line_num, 10, buf + strlen(buf));
438 (void) strcat(buf, "\n");
439 (void) __write(2, buf, strlen(buf));
441 * We could replace the call to Abort() with the following code
442 * if we want just to issue a warning message and not die.
443 * assert_thread = NULL;
444 * _lwp_mutex_unlock(&assert_lock);
445 * if (self != NULL)
446 * exit_critical(self);
448 Abort(buf);
452 * We define and export this version of assfail() just because libaio
453 * used to define and export it, needlessly. Now that libaio is folded
454 * into libc, we need to continue this for ABI/version reasons.
455 * We don't use "#pragma weak assfail __assfail" in order to avoid
456 * warnings from the check_fnames utility at build time for libraries
457 * that define their own version of assfail().
459 void
460 assfail(const char *assertion, const char *filename, int line_num)
462 __assfail(assertion, filename, line_num);
465 void
466 assfail3(const char *assertion, uintmax_t lv, const char *op, uintmax_t rv,
467 const char *filename, int line_num)
469 char buf[1000];
470 (void) strcpy(buf, assertion);
471 (void) strcat(buf, " (");
472 ultos((uint64_t)lv, 16, buf + strlen(buf));
473 (void) strcat(buf, " ");
474 (void) strcat(buf, op);
475 (void) strcat(buf, " ");
476 ultos((uint64_t)rv, 16, buf + strlen(buf));
477 (void) strcat(buf, ")");
478 __assfail(buf, filename, line_num);