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 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 }