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