Home | History | Annotate | Download | only in threads
      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 2009 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
     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
     51 grab_assert_lock()
     52 {
     53 	(void) _lwp_mutex_lock(&assert_lock);
     54 }
     55 
     56 static void
     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, NULL);
     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
     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
    118 thr_panic(const char *why)
    119 {
    120 	common_panic("*** libc thread failure: ", why);
    121 }
    122 
    123 void
    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
    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
    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
    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
    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
    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
    441 assfail(const char *assertion, const char *filename, int line_num)
    442 {
    443 	__assfail(assertion, filename, line_num);
    444 }
    445