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