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 }