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