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