1 /** 2 * testcode/checklocks.c - wrapper on locks that checks access. 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include "config.h" 37 #include <signal.h> 38 #include "util/locks.h" /* include before checklocks.h */ 39 #include "testcode/checklocks.h" 40 41 /** 42 * \file 43 * Locks that are checked. 44 * 45 * Ugly hack: uses the fact that workers start with an int thread_num, and 46 * are passed to thread_create to make the thread numbers here the same as 47 * those used for logging which is nice. 48 * 49 * Todo: 50 * - debug status print, of thread lock stacks, and current waiting. 51 */ 52 #ifdef USE_THREAD_DEBUG 53 54 /** How long to wait before lock attempt is a failure. */ 55 #define CHECK_LOCK_TIMEOUT 120 /* seconds */ 56 /** How long to wait before join attempt is a failure. */ 57 #define CHECK_JOIN_TIMEOUT 120 /* seconds */ 58 59 /** if key has been created */ 60 static int key_created = 0; 61 /** if the key was deleted, i.e. we have quit */ 62 static int key_deleted = 0; 63 /** we hide the thread debug info with this key. */ 64 static ub_thread_key_type thr_debug_key; 65 /** the list of threads, so all threads can be examined. NULL if unused. */ 66 static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS]; 67 /** stored maximum lock number for threads, when a thread is restarted the 68 * number is kept track of, because the new locks get new id numbers. */ 69 static int thread_lockcount[THRDEBUG_MAX_THREADS]; 70 /** do we check locking order */ 71 int check_locking_order = 1; 72 /** the pid of this runset, reasonably unique. */ 73 static pid_t check_lock_pid; 74 /** the name of the output file */ 75 static const char* output_name = "ublocktrace"; 76 /** 77 * Should checklocks print a trace of the lock and unlock calls. 78 * It uses fprintf for that because the log function uses a lock and that 79 * would loop otherwise. 80 */ 81 static int verbose_locking = 0; 82 /** 83 * Assume lock 0 0 (create_thread, create_instance), is the log lock and 84 * do not print for that. Otherwise the output is full of log lock accesses. 85 */ 86 static int verbose_locking_not_loglock = 1; 87 88 /** print all possible debug info on the state of the system */ 89 static void total_debug_info(void); 90 /** print pretty lock error and exit (decl for NORETURN attribute) */ 91 static void lock_error(struct checked_lock* lock, const char* func, 92 const char* file, int line, const char* err) ATTR_NORETURN; 93 94 /** print pretty lock error and exit */ 95 static void lock_error(struct checked_lock* lock, 96 const char* func, const char* file, int line, const char* err) 97 { 98 log_err("lock error (description follows)"); 99 log_err("Created at %s %s:%d", lock->create_func, 100 lock->create_file, lock->create_line); 101 if(lock->holder_func && lock->holder_file) 102 log_err("Previously %s %s:%d", lock->holder_func, 103 lock->holder_file, lock->holder_line); 104 log_err("At %s %s:%d", func, file, line); 105 log_err("Error for %s lock: %s", 106 (lock->type==check_lock_mutex)?"mutex": ( 107 (lock->type==check_lock_spinlock)?"spinlock": ( 108 (lock->type==check_lock_rwlock)?"rwlock": "badtype")), err); 109 log_err("complete status display:"); 110 total_debug_info(); 111 fatal_exit("bailing out"); 112 } 113 114 /** 115 * Obtain lock on debug lock structure. This could be a deadlock by the caller. 116 * The debug code itself does not deadlock. Anyway, check with timeouts. 117 * @param lock: on what to acquire lock. 118 * @param func: user level caller identification. 119 * @param file: user level caller identification. 120 * @param line: user level caller identification. 121 */ 122 static void 123 acquire_locklock(struct checked_lock* lock, 124 const char* func, const char* file, int line) 125 { 126 struct timespec to; 127 int err; 128 int contend = 0; 129 /* first try; inc contention counter if not immediately */ 130 if((err = pthread_mutex_trylock(&lock->lock))) { 131 if(err==EBUSY) 132 contend++; 133 else fatal_exit("error in mutex_trylock: %s", strerror(err)); 134 } 135 if(!err) 136 return; /* immediate success */ 137 to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT; 138 to.tv_nsec = 0; 139 err = pthread_mutex_timedlock(&lock->lock, &to); 140 if(err) { 141 log_err("in acquiring locklock: %s", strerror(err)); 142 lock_error(lock, func, file, line, "acquire locklock"); 143 } 144 /* since we hold the lock, we can edit the contention_count */ 145 lock->contention_count += contend; 146 } 147 148 /** add protected region */ 149 void 150 lock_protect_place(void* p, void* area, size_t size, const char* def_func, 151 const char* def_file, int def_line, const char* def_area) 152 { 153 struct checked_lock* lock = *(struct checked_lock**)p; 154 struct protected_area* e = (struct protected_area*)malloc( 155 sizeof(struct protected_area)); 156 if(!e) 157 fatal_exit("lock_protect: out of memory"); 158 e->region = area; 159 e->size = size; 160 e->def_func = def_func; 161 e->def_file = def_file; 162 e->def_line = def_line; 163 e->def_area = def_area; 164 e->hold = malloc(size); 165 if(!e->hold) 166 fatal_exit("lock_protect: out of memory"); 167 memcpy(e->hold, e->region, e->size); 168 169 acquire_locklock(lock, __func__, __FILE__, __LINE__); 170 e->next = lock->prot; 171 lock->prot = e; 172 LOCKRET(pthread_mutex_unlock(&lock->lock)); 173 } 174 175 /** remove protected region */ 176 void 177 lock_unprotect(void* mangled, void* area) 178 { 179 struct checked_lock* lock = *(struct checked_lock**)mangled; 180 struct protected_area* p, **prevp; 181 if(!lock) 182 return; 183 acquire_locklock(lock, __func__, __FILE__, __LINE__); 184 p = lock->prot; 185 prevp = &lock->prot; 186 while(p) { 187 if(p->region == area) { 188 *prevp = p->next; 189 free(p->hold); 190 free(p); 191 LOCKRET(pthread_mutex_unlock(&lock->lock)); 192 return; 193 } 194 prevp = &p->next; 195 p = p->next; 196 } 197 LOCKRET(pthread_mutex_unlock(&lock->lock)); 198 } 199 200 /** 201 * Check protected memory region. Memory compare. Exit on error. 202 * @param lock: which lock to check. 203 * @param func: location we are now (when failure is detected). 204 * @param file: location we are now (when failure is detected). 205 * @param line: location we are now (when failure is detected). 206 */ 207 static void 208 prot_check(struct checked_lock* lock, 209 const char* func, const char* file, int line) 210 { 211 struct protected_area* p = lock->prot; 212 while(p) { 213 if(memcmp(p->hold, p->region, p->size) != 0) { 214 log_hex("memory prev", p->hold, p->size); 215 log_hex("memory here", p->region, p->size); 216 log_err("lock_protect on %s %s:%d %s failed", 217 p->def_func, p->def_file, p->def_line, 218 p->def_area); 219 lock_error(lock, func, file, line, 220 "protected area modified"); 221 } 222 p = p->next; 223 } 224 } 225 226 /** Copy protected memory region */ 227 static void 228 prot_store(struct checked_lock* lock) 229 { 230 struct protected_area* p = lock->prot; 231 while(p) { 232 memcpy(p->hold, p->region, p->size); 233 p = p->next; 234 } 235 } 236 237 /** get memory held by lock */ 238 size_t 239 lock_get_mem(void* pp) 240 { 241 size_t s; 242 struct checked_lock* lock = *(struct checked_lock**)pp; 243 struct protected_area* p; 244 s = sizeof(struct checked_lock); 245 acquire_locklock(lock, __func__, __FILE__, __LINE__); 246 for(p = lock->prot; p; p = p->next) { 247 s += sizeof(struct protected_area); 248 s += p->size; 249 } 250 LOCKRET(pthread_mutex_unlock(&lock->lock)); 251 return s; 252 } 253 254 /** write lock trace info to file, while you hold those locks */ 255 static void 256 ordercheck_locklock(struct thr_check* thr, struct checked_lock* lock) 257 { 258 int info[4]; 259 if(!check_locking_order) return; 260 if(!thr->holding_first) return; /* no older lock, no info */ 261 /* write: <lock id held> <lock id new> <file> <line> */ 262 info[0] = thr->holding_first->create_thread; 263 info[1] = thr->holding_first->create_instance; 264 info[2] = lock->create_thread; 265 info[3] = lock->create_instance; 266 if(fwrite(info, 4*sizeof(int), 1, thr->order_info) != 1 || 267 fwrite(lock->holder_file, strlen(lock->holder_file)+1, 1, 268 thr->order_info) != 1 || 269 fwrite(&lock->holder_line, sizeof(int), 1, 270 thr->order_info) != 1) 271 log_err("fwrite: %s", strerror(errno)); 272 } 273 274 /** write ordercheck lock creation details to file */ 275 static void 276 ordercheck_lockcreate(struct thr_check* thr, struct checked_lock* lock) 277 { 278 /* write: <ffff = create> <lock id> <file> <line> */ 279 int cmd = -1; 280 if(!check_locking_order) return; 281 282 if( fwrite(&cmd, sizeof(int), 1, thr->order_info) != 1 || 283 fwrite(&lock->create_thread, sizeof(int), 1, 284 thr->order_info) != 1 || 285 fwrite(&lock->create_instance, sizeof(int), 1, 286 thr->order_info) != 1 || 287 fwrite(lock->create_file, strlen(lock->create_file)+1, 1, 288 thr->order_info) != 1 || 289 fwrite(&lock->create_line, sizeof(int), 1, 290 thr->order_info) != 1) 291 log_err("fwrite: %s", strerror(errno)); 292 } 293 294 /** alloc struct, init lock empty */ 295 void 296 checklock_init(enum check_lock_type type, struct checked_lock** lock, 297 const char* func, const char* file, int line) 298 { 299 struct checked_lock* e = (struct checked_lock*)calloc(1, 300 sizeof(struct checked_lock)); 301 struct thr_check *thr = (struct thr_check*)pthread_getspecific( 302 thr_debug_key); 303 if(!e) 304 fatal_exit("%s %s %d: out of memory", func, file, line); 305 if(!thr) { 306 /* this is called when log_init() calls lock_init() 307 * functions, and the test check code has not yet 308 * been initialised. But luckily, the checklock_start() 309 * routine can be called multiple times without ill effect. 310 */ 311 checklock_start(); 312 thr = (struct thr_check*)pthread_getspecific(thr_debug_key); 313 } 314 if(!thr) 315 fatal_exit("%s %s %d: lock_init no thread info", func, file, 316 line); 317 *lock = e; 318 e->type = type; 319 e->create_func = func; 320 e->create_file = file; 321 e->create_line = line; 322 e->create_thread = thr->num; 323 e->create_instance = thr->locks_created++; 324 ordercheck_lockcreate(thr, e); 325 LOCKRET(pthread_mutex_init(&e->lock, NULL)); 326 switch(e->type) { 327 case check_lock_mutex: 328 LOCKRET(pthread_mutex_init(&e->u.mutex, NULL)); 329 break; 330 case check_lock_spinlock: 331 LOCKRET(pthread_spin_init(&e->u.spinlock, PTHREAD_PROCESS_PRIVATE)); 332 break; 333 case check_lock_rwlock: 334 LOCKRET(pthread_rwlock_init(&e->u.rwlock, NULL)); 335 break; 336 default: 337 log_assert(0); 338 } 339 } 340 341 /** delete prot items */ 342 static void 343 prot_clear(struct checked_lock* lock) 344 { 345 struct protected_area* p=lock->prot, *np; 346 while(p) { 347 np = p->next; 348 free(p->hold); 349 free(p); 350 p = np; 351 } 352 } 353 354 /** check if type is OK for the lock given */ 355 static void 356 checktype(enum check_lock_type type, struct checked_lock* lock, 357 const char* func, const char* file, int line) 358 { 359 if(!lock) 360 fatal_exit("use of null/deleted lock at %s %s:%d", 361 func, file, line); 362 if(type != lock->type) { 363 lock_error(lock, func, file, line, "wrong lock type"); 364 } 365 } 366 367 /** check if OK, free struct */ 368 void 369 checklock_destroy(enum check_lock_type type, struct checked_lock** lock, 370 const char* func, const char* file, int line) 371 { 372 const size_t contention_interest = 1; /* promille contented locks */ 373 struct checked_lock* e; 374 if(!lock) 375 return; 376 e = *lock; 377 if(!e) 378 return; 379 checktype(type, e, func, file, line); 380 381 /* check if delete is OK */ 382 acquire_locklock(e, func, file, line); 383 if(e->hold_count != 0) 384 lock_error(e, func, file, line, "delete while locked."); 385 if(e->wait_count != 0) 386 lock_error(e, func, file, line, "delete while waited on."); 387 prot_check(e, func, file, line); 388 *lock = NULL; /* use after free will fail */ 389 LOCKRET(pthread_mutex_unlock(&e->lock)); 390 391 /* contention, look at fraction in trouble. */ 392 if(e->history_count > 1 && 393 1000*e->contention_count/e->history_count > contention_interest) { 394 log_info("lock created %s %s %d has contention %u of %u (%d%%)", 395 e->create_func, e->create_file, e->create_line, 396 (unsigned int)e->contention_count, 397 (unsigned int)e->history_count, 398 (int)(100*e->contention_count/e->history_count)); 399 } 400 401 /* delete it */ 402 LOCKRET(pthread_mutex_destroy(&e->lock)); 403 prot_clear(e); 404 /* since nobody holds the lock - see check above, no need to unlink 405 * from the thread-held locks list. */ 406 switch(e->type) { 407 case check_lock_mutex: 408 LOCKRET(pthread_mutex_destroy(&e->u.mutex)); 409 break; 410 case check_lock_spinlock: 411 LOCKRET(pthread_spin_destroy(&e->u.spinlock)); 412 break; 413 case check_lock_rwlock: 414 LOCKRET(pthread_rwlock_destroy(&e->u.rwlock)); 415 break; 416 default: 417 log_assert(0); 418 } 419 memset(e, 0, sizeof(struct checked_lock)); 420 free(e); 421 } 422 423 /** finish acquiring lock, shared between _(rd|wr||)lock() routines */ 424 static void 425 finish_acquire_lock(struct thr_check* thr, struct checked_lock* lock, 426 const char* func, const char* file, int line) 427 { 428 thr->waiting = NULL; 429 lock->wait_count --; 430 lock->holder = thr; 431 lock->hold_count ++; 432 lock->holder_func = func; 433 lock->holder_file = file; 434 lock->holder_line = line; 435 ordercheck_locklock(thr, lock); 436 437 /* insert in thread lock list, as first */ 438 lock->prev_held_lock[thr->num] = NULL; 439 lock->next_held_lock[thr->num] = thr->holding_first; 440 if(thr->holding_first) 441 /* no need to lock it, since this thread already holds the 442 * lock (since it is on this list) and we only edit thr->num 443 * member in array. So it is safe. */ 444 thr->holding_first->prev_held_lock[thr->num] = lock; 445 else thr->holding_last = lock; 446 thr->holding_first = lock; 447 } 448 449 /** 450 * Locking routine. 451 * @param type: as passed by user. 452 * @param lock: as passed by user. 453 * @param func: caller location. 454 * @param file: caller location. 455 * @param line: caller location. 456 * @param tryfunc: the pthread_mutex_trylock or similar function. 457 * @param timedfunc: the pthread_mutex_timedlock or similar function. 458 * Uses absolute timeout value. 459 * @param arg: what to pass to tryfunc and timedlock. 460 * @param exclusive: if lock must be exclusive (only one allowed). 461 * @param getwr: if attempts to get writelock (or readlock) for rwlocks. 462 */ 463 static void 464 checklock_lockit(enum check_lock_type type, struct checked_lock* lock, 465 const char* func, const char* file, int line, 466 int (*tryfunc)(void*), int (*timedfunc)(void*, struct timespec*), 467 void* arg, int exclusive, int getwr) 468 { 469 int err; 470 int contend = 0; 471 struct thr_check *thr = (struct thr_check*)pthread_getspecific( 472 thr_debug_key); 473 checktype(type, lock, func, file, line); 474 if(!thr) lock_error(lock, func, file, line, "no thread info"); 475 476 acquire_locklock(lock, func, file, line); 477 lock->wait_count ++; 478 thr->waiting = lock; 479 if(exclusive && lock->hold_count > 0 && lock->holder == thr) 480 lock_error(lock, func, file, line, "thread already owns lock"); 481 if(type==check_lock_rwlock && getwr && lock->writeholder == thr) 482 lock_error(lock, func, file, line, "thread already has wrlock"); 483 LOCKRET(pthread_mutex_unlock(&lock->lock)); 484 485 /* first try; if busy increase contention counter */ 486 if((err=tryfunc(arg))) { 487 struct timespec to; 488 if(err != EBUSY) log_err("trylock: %s", strerror(err)); 489 to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT; 490 to.tv_nsec = 0; 491 if((err=timedfunc(arg, &to))) { 492 if(err == ETIMEDOUT) 493 lock_error(lock, func, file, line, 494 "timeout possible deadlock"); 495 log_err("timedlock: %s", strerror(err)); 496 } 497 contend ++; 498 } 499 /* got the lock */ 500 501 acquire_locklock(lock, func, file, line); 502 lock->contention_count += contend; 503 lock->history_count++; 504 if(exclusive && lock->hold_count > 0) 505 lock_error(lock, func, file, line, "got nonexclusive lock"); 506 if(type==check_lock_rwlock && getwr && lock->writeholder) 507 lock_error(lock, func, file, line, "got nonexclusive wrlock"); 508 if(type==check_lock_rwlock && getwr) 509 lock->writeholder = thr; 510 /* check the memory areas for unauthorized changes, 511 * between last unlock time and current lock time. 512 * we check while holding the lock (threadsafe). 513 */ 514 if(getwr || exclusive) 515 prot_check(lock, func, file, line); 516 finish_acquire_lock(thr, lock, func, file, line); 517 LOCKRET(pthread_mutex_unlock(&lock->lock)); 518 } 519 520 /** helper for rdlock: try */ 521 static int try_rd(void* arg) 522 { return pthread_rwlock_tryrdlock((pthread_rwlock_t*)arg); } 523 /** helper for rdlock: timed */ 524 static int timed_rd(void* arg, struct timespec* to) 525 { return pthread_rwlock_timedrdlock((pthread_rwlock_t*)arg, to); } 526 527 /** check if OK, lock */ 528 void 529 checklock_rdlock(enum check_lock_type type, struct checked_lock* lock, 530 const char* func, const char* file, int line) 531 { 532 if(key_deleted) 533 return; 534 535 if(verbose_locking && !(verbose_locking_not_loglock && 536 lock->create_thread == 0 && lock->create_instance == 0)) 537 fprintf(stderr, "checklock_rdlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); 538 log_assert(type == check_lock_rwlock); 539 checklock_lockit(type, lock, func, file, line, 540 try_rd, timed_rd, &lock->u.rwlock, 0, 0); 541 } 542 543 /** helper for wrlock: try */ 544 static int try_wr(void* arg) 545 { return pthread_rwlock_trywrlock((pthread_rwlock_t*)arg); } 546 /** helper for wrlock: timed */ 547 static int timed_wr(void* arg, struct timespec* to) 548 { return pthread_rwlock_timedwrlock((pthread_rwlock_t*)arg, to); } 549 550 /** check if OK, lock */ 551 void 552 checklock_wrlock(enum check_lock_type type, struct checked_lock* lock, 553 const char* func, const char* file, int line) 554 { 555 if(key_deleted) 556 return; 557 log_assert(type == check_lock_rwlock); 558 if(verbose_locking && !(verbose_locking_not_loglock && 559 lock->create_thread == 0 && lock->create_instance == 0)) 560 fprintf(stderr, "checklock_wrlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); 561 checklock_lockit(type, lock, func, file, line, 562 try_wr, timed_wr, &lock->u.rwlock, 0, 1); 563 } 564 565 /** helper for lock mutex: try */ 566 static int try_mutex(void* arg) 567 { return pthread_mutex_trylock((pthread_mutex_t*)arg); } 568 /** helper for lock mutex: timed */ 569 static int timed_mutex(void* arg, struct timespec* to) 570 { return pthread_mutex_timedlock((pthread_mutex_t*)arg, to); } 571 572 /** helper for lock spinlock: try */ 573 static int try_spinlock(void* arg) 574 { return pthread_spin_trylock((pthread_spinlock_t*)arg); } 575 /** helper for lock spinlock: timed */ 576 static int timed_spinlock(void* arg, struct timespec* to) 577 { 578 int err; 579 /* spin for 5 seconds. (ouch for the CPU, but it beats forever) */ 580 while( (err=try_spinlock(arg)) == EBUSY) { 581 #ifndef S_SPLINT_S 582 if(time(NULL) >= to->tv_sec) 583 return ETIMEDOUT; 584 usleep(1000); /* in 1/1000000s of a second */ 585 #endif 586 } 587 return err; 588 } 589 590 /** check if OK, lock */ 591 void 592 checklock_lock(enum check_lock_type type, struct checked_lock* lock, 593 const char* func, const char* file, int line) 594 { 595 if(key_deleted) 596 return; 597 log_assert(type != check_lock_rwlock); 598 if(verbose_locking && !(verbose_locking_not_loglock && 599 lock->create_thread == 0 && lock->create_instance == 0)) 600 fprintf(stderr, "checklock_lock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); 601 switch(type) { 602 case check_lock_mutex: 603 checklock_lockit(type, lock, func, file, line, 604 try_mutex, timed_mutex, &lock->u.mutex, 1, 0); 605 break; 606 case check_lock_spinlock: 607 /* void* cast needed because 'volatile' on some OS */ 608 checklock_lockit(type, lock, func, file, line, 609 try_spinlock, timed_spinlock, 610 (void*)&lock->u.spinlock, 1, 0); 611 break; 612 default: 613 log_assert(0); 614 } 615 } 616 617 /** check if OK, unlock */ 618 void 619 checklock_unlock(enum check_lock_type type, struct checked_lock* lock, 620 const char* func, const char* file, int line) 621 { 622 struct thr_check *thr; 623 if(key_deleted) 624 return; 625 thr = (struct thr_check*)pthread_getspecific(thr_debug_key); 626 checktype(type, lock, func, file, line); 627 if(!thr) lock_error(lock, func, file, line, "no thread info"); 628 629 acquire_locklock(lock, func, file, line); 630 /* was this thread even holding this lock? */ 631 if(thr->holding_first != lock && 632 lock->prev_held_lock[thr->num] == NULL) { 633 lock_error(lock, func, file, line, "unlock nonlocked lock"); 634 } 635 if(lock->hold_count <= 0) 636 lock_error(lock, func, file, line, "too many unlocks"); 637 638 if(verbose_locking && !(verbose_locking_not_loglock && 639 lock->create_thread == 0 && lock->create_instance == 0)) 640 fprintf(stderr, "checklock_unlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line); 641 642 /* store this point as last touched by */ 643 lock->holder = thr; 644 lock->hold_count --; 645 lock->holder_func = func; 646 lock->holder_file = file; 647 lock->holder_line = line; 648 649 /* delete from thread holder list */ 650 /* no need to lock other lockstructs, because they are all on the 651 * held-locks list, and this thread holds their locks. 652 * we only touch the thr->num members, so it is safe. */ 653 if(thr->holding_first == lock) 654 thr->holding_first = lock->next_held_lock[thr->num]; 655 if(thr->holding_last == lock) 656 thr->holding_last = lock->prev_held_lock[thr->num]; 657 if(lock->next_held_lock[thr->num]) 658 lock->next_held_lock[thr->num]->prev_held_lock[thr->num] = 659 lock->prev_held_lock[thr->num]; 660 if(lock->prev_held_lock[thr->num]) 661 lock->prev_held_lock[thr->num]->next_held_lock[thr->num] = 662 lock->next_held_lock[thr->num]; 663 lock->next_held_lock[thr->num] = NULL; 664 lock->prev_held_lock[thr->num] = NULL; 665 666 if(type==check_lock_rwlock && lock->writeholder == thr) { 667 lock->writeholder = NULL; 668 prot_store(lock); 669 } else if(type != check_lock_rwlock) { 670 /* store memory areas that are protected, for later checks */ 671 prot_store(lock); 672 } 673 LOCKRET(pthread_mutex_unlock(&lock->lock)); 674 675 /* unlock it */ 676 switch(type) { 677 case check_lock_mutex: 678 LOCKRET(pthread_mutex_unlock(&lock->u.mutex)); 679 break; 680 case check_lock_spinlock: 681 LOCKRET(pthread_spin_unlock(&lock->u.spinlock)); 682 break; 683 case check_lock_rwlock: 684 LOCKRET(pthread_rwlock_unlock(&lock->u.rwlock)); 685 break; 686 default: 687 log_assert(0); 688 } 689 } 690 691 void 692 checklock_set_output_name(const char* name) 693 { 694 output_name = name; 695 } 696 697 /** open order info debug file, thr->num must be valid */ 698 static void 699 open_lockorder(struct thr_check* thr) 700 { 701 char buf[24]; 702 time_t t; 703 snprintf(buf, sizeof(buf), "%s.%d", output_name, thr->num); 704 thr->locks_created = thread_lockcount[thr->num]; 705 if(thr->locks_created == 0) { 706 thr->order_info = fopen(buf, "w"); 707 if(!thr->order_info) 708 fatal_exit("could not open %s: %s", buf, strerror(errno)); 709 } else { 710 /* There is already a file to append on with the previous 711 * thread information. */ 712 thr->order_info = fopen(buf, "a"); 713 if(!thr->order_info) 714 fatal_exit("could not open for append %s: %s", buf, strerror(errno)); 715 return; 716 } 717 718 t = time(NULL); 719 /* write: <time_stamp> <runpid> <thread_num> */ 720 if(fwrite(&t, sizeof(t), 1, thr->order_info) != 1 || 721 fwrite(&thr->num, sizeof(thr->num), 1, thr->order_info) != 1 || 722 fwrite(&check_lock_pid, sizeof(check_lock_pid), 1, 723 thr->order_info) != 1) 724 log_err("fwrite: %s", strerror(errno)); 725 } 726 727 /** checklock thread main, Inits thread structure */ 728 static void* checklock_main(void* arg) 729 { 730 struct thr_check* thr = (struct thr_check*)arg; 731 void* ret; 732 thr->id = pthread_self(); 733 /* Hack to get same numbers as in log file */ 734 thr->num = *(int*)(thr->arg); 735 log_assert(thr->num < THRDEBUG_MAX_THREADS); 736 /* as an aside, due to this, won't work for libunbound bg thread */ 737 if(thread_infos[thr->num] != NULL) 738 log_warn("thread warning, thr->num %d not NULL", thr->num); 739 thread_infos[thr->num] = thr; 740 LOCKRET(pthread_setspecific(thr_debug_key, thr)); 741 if(check_locking_order) 742 open_lockorder(thr); 743 ret = thr->func(thr->arg); 744 thread_lockcount[thr->num] = thr->locks_created; 745 thread_infos[thr->num] = NULL; 746 if(check_locking_order) 747 fclose(thr->order_info); 748 free(thr); 749 return ret; 750 } 751 752 /** init the main thread */ 753 void checklock_start(void) 754 { 755 if(key_deleted) 756 return; 757 if(!key_created) { 758 struct thr_check* thisthr = (struct thr_check*)calloc(1, 759 sizeof(struct thr_check)); 760 if(!thisthr) 761 fatal_exit("thrcreate: out of memory"); 762 key_created = 1; 763 check_lock_pid = getpid(); 764 LOCKRET(pthread_key_create(&thr_debug_key, NULL)); 765 LOCKRET(pthread_setspecific(thr_debug_key, thisthr)); 766 thread_infos[0] = thisthr; 767 if(check_locking_order) 768 open_lockorder(thisthr); 769 } 770 } 771 772 /** stop checklocks */ 773 void checklock_stop(void) 774 { 775 if(key_created) { 776 int i; 777 key_deleted = 1; 778 if(check_locking_order) 779 fclose(thread_infos[0]->order_info); 780 free(thread_infos[0]); 781 thread_infos[0] = NULL; 782 for(i = 0; i < THRDEBUG_MAX_THREADS; i++) 783 log_assert(thread_infos[i] == NULL); 784 /* should have been cleaned up. */ 785 LOCKRET(pthread_key_delete(thr_debug_key)); 786 key_created = 0; 787 } 788 } 789 790 /** allocate debug info and create thread */ 791 void 792 checklock_thrcreate(pthread_t* id, void* (*func)(void*), void* arg) 793 { 794 struct thr_check* thr = (struct thr_check*)calloc(1, 795 sizeof(struct thr_check)); 796 if(!thr) 797 fatal_exit("thrcreate: out of memory"); 798 if(!key_created) { 799 checklock_start(); 800 } 801 thr->func = func; 802 thr->arg = arg; 803 LOCKRET(pthread_create(id, NULL, checklock_main, thr)); 804 } 805 806 /** count number of thread infos */ 807 static int 808 count_thread_infos(void) 809 { 810 int cnt = 0; 811 int i; 812 for(i=0; i<THRDEBUG_MAX_THREADS; i++) 813 if(thread_infos[i]) 814 cnt++; 815 return cnt; 816 } 817 818 /** print lots of info on a lock */ 819 static void 820 lock_debug_info(struct checked_lock* lock) 821 { 822 if(!lock) return; 823 log_info("+++ Lock %llx, %d %d create %s %s %d", 824 (unsigned long long)(size_t)lock, 825 lock->create_thread, lock->create_instance, 826 lock->create_func, lock->create_file, lock->create_line); 827 log_info("lock type: %s", 828 (lock->type==check_lock_mutex)?"mutex": ( 829 (lock->type==check_lock_spinlock)?"spinlock": ( 830 (lock->type==check_lock_rwlock)?"rwlock": "badtype"))); 831 log_info("lock contention %u, history:%u, hold:%d, wait:%d", 832 (unsigned)lock->contention_count, (unsigned)lock->history_count, 833 lock->hold_count, lock->wait_count); 834 log_info("last touch %s %s %d", lock->holder_func, lock->holder_file, 835 lock->holder_line); 836 log_info("holder thread %d, writeholder thread %d", 837 lock->holder?lock->holder->num:-1, 838 lock->writeholder?lock->writeholder->num:-1); 839 } 840 841 /** print debug locks held by a thread */ 842 static void 843 held_debug_info(struct thr_check* thr, struct checked_lock* lock) 844 { 845 if(!lock) return; 846 lock_debug_info(lock); 847 held_debug_info(thr, lock->next_held_lock[thr->num]); 848 } 849 850 /** print debug info for a thread */ 851 static void 852 thread_debug_info(struct thr_check* thr) 853 { 854 struct checked_lock* w = NULL; 855 struct checked_lock* f = NULL; 856 struct checked_lock* l = NULL; 857 if(!thr) return; 858 log_info("pthread id is %x", (int)thr->id); 859 log_info("thread func is %llx", (unsigned long long)(size_t)thr->func); 860 log_info("thread arg is %llx (%d)", 861 (unsigned long long)(size_t)thr->arg, 862 (thr->arg?*(int*)thr->arg:0)); 863 log_info("thread num is %d", thr->num); 864 log_info("locks created %d", thr->locks_created); 865 log_info("open file for lockinfo: %s", 866 thr->order_info?"yes, flushing":"no"); 867 fflush(thr->order_info); 868 w = thr->waiting; 869 f = thr->holding_first; 870 l = thr->holding_last; 871 log_info("thread waiting for a lock: %s %llx", w?"yes":"no", 872 (unsigned long long)(size_t)w); 873 lock_debug_info(w); 874 log_info("thread holding first: %s, last: %s", f?"yes":"no", 875 l?"yes":"no"); 876 held_debug_info(thr, f); 877 } 878 879 static void 880 total_debug_info(void) 881 { 882 int i; 883 log_info("checklocks: supervising %d threads.", 884 count_thread_infos()); 885 if(!key_created) { 886 log_info("No thread debug key created yet"); 887 } 888 for(i=0; i<THRDEBUG_MAX_THREADS; i++) { 889 if(thread_infos[i]) { 890 log_info("*** Thread %d information: ***", i); 891 thread_debug_info(thread_infos[i]); 892 } 893 } 894 } 895 896 /** signal handler for join timeout, Exits */ 897 static RETSIGTYPE joinalarm(int ATTR_UNUSED(sig)) 898 { 899 log_err("join thread timeout. hangup or deadlock. Info follows."); 900 total_debug_info(); 901 fatal_exit("join thread timeout. hangup or deadlock."); 902 } 903 904 /** wait for thread with a timeout */ 905 void 906 checklock_thrjoin(pthread_t thread) 907 { 908 /* wait with a timeout */ 909 if(signal(SIGALRM, joinalarm) == SIG_ERR) 910 fatal_exit("signal(): %s", strerror(errno)); 911 (void)alarm(CHECK_JOIN_TIMEOUT); 912 LOCKRET(pthread_join(thread, NULL)); 913 (void)alarm(0); 914 } 915 916 #endif /* USE_THREAD_DEBUG */ 917