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