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