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