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