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 2010 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); 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