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