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 2007 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 uint32_t rwstate; 252 char buf[800]; 253 uberdata_t *udp; 254 ulwp_t *self; 255 lwpid_t lwpid; 256 pid_t pid; 257 int process; 258 259 /* avoid recursion deadlock */ 260 if ((self = __curthread()) != NULL) { 261 if (assert_thread == self) 262 _exit(127); 263 enter_critical(self); 264 (void) _private_lwp_mutex_lock(&assert_lock); 265 assert_thread = self; 266 lwpid = self->ul_lwpid; 267 udp = self->ul_uberdata; 268 pid = udp->pid; 269 } else { 270 self = NULL; 271 (void) _private_lwp_mutex_lock(&assert_lock); 272 lwpid = __lwp_self(); 273 udp = &__uberdata; 274 pid = _private_getpid(); 275 } 276 277 rwstate = (uint32_t)rcopy.rwlock_readers; 278 process = (rcopy.rwlock_type & USYNC_PROCESS); 279 280 (void) strcpy(buf, 281 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n"); 282 (void) strcat(buf, who); 283 (void) strcat(buf, "("); 284 ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf)); 285 (void) strcat(buf, "): "); 286 (void) strcat(buf, msg); 287 (void) strcat(buf, "\ncalling thread is "); 288 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); 289 (void) strcat(buf, " thread-id "); 290 ultos((uint64_t)lwpid, 10, buf + strlen(buf)); 291 if (process) { 292 (void) strcat(buf, " in process "); 293 ultos((uint64_t)pid, 10, buf + strlen(buf)); 294 } 295 if (rwstate & URW_WRITE_LOCKED) { 296 (void) strcat(buf, "\nthe writer lock owner is "); 297 ultos((uint64_t)rcopy.rwlock_owner, 16, 298 buf + strlen(buf)); 299 if (process) { 300 (void) strcat(buf, " in process "); 301 ultos((uint64_t)rcopy.rwlock_ownerpid, 10, 302 buf + strlen(buf)); 303 } 304 } else if (rwstate & URW_READERS_MASK) { 305 (void) strcat(buf, "\nthe reader lock is held by "); 306 ultos((uint64_t)(rwstate & URW_READERS_MASK), 10, 307 buf + strlen(buf)); 308 (void) strcat(buf, " readers"); 309 } else { 310 (void) strcat(buf, "\nthe lock is unowned"); 311 } 312 if (rwstate & URW_HAS_WAITERS) 313 (void) strcat(buf, "\nand the lock appears to have waiters"); 314 (void) strcat(buf, "\n\n"); 315 (void) _write(2, buf, strlen(buf)); 316 if (udp->uberflags.uf_thread_error_detection >= 2) 317 Abort(buf); 318 assert_thread = NULL; 319 (void) _private_lwp_mutex_unlock(&assert_lock); 320 if (self != NULL) 321 exit_critical(self); 322 } 323 324 /* 325 * Report a thread usage error. 326 * Not called if _THREAD_ERROR_DETECTION=0. 327 * Writes message and continues execution if _THREAD_ERROR_DETECTION=1. 328 * Writes message and dumps core if _THREAD_ERROR_DETECTION=2. 329 */ 330 void 331 thread_error(const char *msg) 332 { 333 char buf[800]; 334 uberdata_t *udp; 335 ulwp_t *self; 336 lwpid_t lwpid; 337 338 /* avoid recursion deadlock */ 339 if ((self = __curthread()) != NULL) { 340 if (assert_thread == self) 341 _exit(127); 342 enter_critical(self); 343 (void) _private_lwp_mutex_lock(&assert_lock); 344 assert_thread = self; 345 lwpid = self->ul_lwpid; 346 udp = self->ul_uberdata; 347 } else { 348 self = NULL; 349 (void) _private_lwp_mutex_lock(&assert_lock); 350 lwpid = __lwp_self(); 351 udp = &__uberdata; 352 } 353 354 (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: " 355 "thread usage error detected ***\n*** "); 356 (void) strcat(buf, msg); 357 358 (void) strcat(buf, "\n*** calling thread is "); 359 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); 360 (void) strcat(buf, " thread-id "); 361 ultos((uint64_t)lwpid, 10, buf + strlen(buf)); 362 (void) strcat(buf, "\n\n"); 363 (void) _write(2, buf, strlen(buf)); 364 if (udp->uberflags.uf_thread_error_detection >= 2) 365 Abort(buf); 366 assert_thread = NULL; 367 (void) _private_lwp_mutex_unlock(&assert_lock); 368 if (self != NULL) 369 exit_critical(self); 370 } 371 372 /* 373 * We use __assfail() because the libc __assert() calls 374 * gettext() which calls malloc() which grabs a mutex. 375 * We do everything without calling standard i/o. 376 * assfail() and _assfail() are exported functions; 377 * __assfail() is private to libc. 378 */ 379 #pragma weak _assfail = __assfail 380 void 381 __assfail(const char *assertion, const char *filename, int line_num) 382 { 383 char buf[800]; /* no assert() message in the library is this long */ 384 ulwp_t *self; 385 lwpid_t lwpid; 386 387 /* avoid recursion deadlock */ 388 if ((self = __curthread()) != NULL) { 389 if (assert_thread == self) 390 _exit(127); 391 enter_critical(self); 392 (void) _private_lwp_mutex_lock(&assert_lock); 393 assert_thread = self; 394 lwpid = self->ul_lwpid; 395 } else { 396 self = NULL; 397 (void) _private_lwp_mutex_lock(&assert_lock); 398 lwpid = __lwp_self(); 399 } 400 401 (void) strcpy(buf, "assertion failed for thread "); 402 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); 403 (void) strcat(buf, ", thread-id "); 404 ultos((uint64_t)lwpid, 10, buf + strlen(buf)); 405 (void) strcat(buf, ": "); 406 (void) strcat(buf, assertion); 407 (void) strcat(buf, ", file "); 408 (void) strcat(buf, filename); 409 (void) strcat(buf, ", line "); 410 ultos((uint64_t)line_num, 10, buf + strlen(buf)); 411 (void) strcat(buf, "\n"); 412 (void) _write(2, buf, strlen(buf)); 413 /* 414 * We could replace the call to Abort() with the following code 415 * if we want just to issue a warning message and not die. 416 * assert_thread = NULL; 417 * _private_lwp_mutex_unlock(&assert_lock); 418 * if (self != NULL) 419 * exit_critical(self); 420 */ 421 Abort(buf); 422 } 423 424 /* 425 * We define and export this version of assfail() just because libaio 426 * used to define and export it, needlessly. Now that libaio is folded 427 * into libc, we need to continue this for ABI/version reasons. 428 * We don't use "#pragma weak assfail __assfail" in order to avoid 429 * warnings from the check_fnames utility at build time for libraries 430 * that define their own version of assfail(). 431 */ 432 void 433 assfail(const char *assertion, const char *filename, int line_num) 434 { 435 __assfail(assertion, filename, line_num); 436 } 437