1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-memory.c D-Bus memory handling 3 * 4 * Copyright (C) 2002, 2003 Red Hat Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 #include "dbus-memory.h" 26 #include "dbus-internals.h" 27 #include "dbus-sysdeps.h" 28 #include "dbus-list.h" 29 #include <stdlib.h> 30 31 /** 32 * @defgroup DBusMemory Memory Allocation 33 * @ingroup DBus 34 * @brief dbus_malloc(), dbus_free(), etc. 35 * 36 * Functions and macros related to allocating and releasing 37 * blocks of memory. 38 * 39 */ 40 41 /** 42 * @defgroup DBusMemoryInternals Memory allocation implementation details 43 * @ingroup DBusInternals 44 * @brief internals of dbus_malloc() etc. 45 * 46 * Implementation details related to allocating and releasing blocks 47 * of memory. 48 */ 49 50 /** 51 * @addtogroup DBusMemory 52 * 53 * @{ 54 */ 55 56 /** 57 * @def dbus_new 58 * 59 * Safe macro for using dbus_malloc(). Accepts the type 60 * to allocate and the number of type instances to 61 * allocate as arguments, and returns a memory block 62 * cast to the desired type, instead of as a void*. 63 * 64 * @param type type name to allocate 65 * @param count number of instances in the allocated array 66 * @returns the new memory block or #NULL on failure 67 */ 68 69 /** 70 * @def dbus_new0 71 * 72 * Safe macro for using dbus_malloc0(). Accepts the type 73 * to allocate and the number of type instances to 74 * allocate as arguments, and returns a memory block 75 * cast to the desired type, instead of as a void*. 76 * The allocated array is initialized to all-bits-zero. 77 * 78 * @param type type name to allocate 79 * @param count number of instances in the allocated array 80 * @returns the new memory block or #NULL on failure 81 */ 82 83 /** 84 * @typedef DBusFreeFunction 85 * 86 * The type of a function which frees a block of memory. 87 * 88 * @param memory the memory to free 89 */ 90 91 /** @} */ /* end of public API docs */ 92 93 /** 94 * @addtogroup DBusMemoryInternals 95 * 96 * @{ 97 */ 98 99 #ifdef DBUS_BUILD_TESTS 100 static dbus_bool_t debug_initialized = FALSE; 101 static int fail_nth = -1; 102 static size_t fail_size = 0; 103 static int fail_alloc_counter = _DBUS_INT_MAX; 104 static int n_failures_per_failure = 1; 105 static int n_failures_this_failure = 0; 106 static dbus_bool_t guards = FALSE; 107 static dbus_bool_t disable_mem_pools = FALSE; 108 static dbus_bool_t backtrace_on_fail_alloc = FALSE; 109 static dbus_bool_t malloc_cannot_fail = FALSE; 110 static DBusAtomic n_blocks_outstanding = {0}; 111 112 /** value stored in guard padding for debugging buffer overrun */ 113 #define GUARD_VALUE 0xdeadbeef 114 /** size of the information about the block stored in guard mode */ 115 #define GUARD_INFO_SIZE 8 116 /** size of the GUARD_VALUE-filled padding after the header info */ 117 #define GUARD_START_PAD 16 118 /** size of the GUARD_VALUE-filled padding at the end of the block */ 119 #define GUARD_END_PAD 16 120 /** size of stuff at start of block */ 121 #define GUARD_START_OFFSET (GUARD_START_PAD + GUARD_INFO_SIZE) 122 /** total extra size over the requested allocation for guard stuff */ 123 #define GUARD_EXTRA_SIZE (GUARD_START_OFFSET + GUARD_END_PAD) 124 125 static void 126 _dbus_initialize_malloc_debug (void) 127 { 128 if (!debug_initialized) 129 { 130 debug_initialized = TRUE; 131 132 if (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH") != NULL) 133 { 134 fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH")); 135 fail_alloc_counter = fail_nth; 136 _dbus_verbose ("Will fail dbus_malloc every %d times\n", fail_nth); 137 } 138 139 if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL) 140 { 141 fail_size = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN")); 142 _dbus_verbose ("Will fail mallocs over %ld bytes\n", 143 (long) fail_size); 144 } 145 146 if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL) 147 { 148 guards = TRUE; 149 _dbus_verbose ("Will use dbus_malloc guards\n"); 150 } 151 152 if (_dbus_getenv ("DBUS_DISABLE_MEM_POOLS") != NULL) 153 { 154 disable_mem_pools = TRUE; 155 _dbus_verbose ("Will disable memory pools\n"); 156 } 157 158 if (_dbus_getenv ("DBUS_MALLOC_BACKTRACES") != NULL) 159 { 160 backtrace_on_fail_alloc = TRUE; 161 _dbus_verbose ("Will backtrace on failing a dbus_malloc\n"); 162 } 163 164 if (_dbus_getenv ("DBUS_MALLOC_CANNOT_FAIL") != NULL) 165 { 166 malloc_cannot_fail = TRUE; 167 _dbus_verbose ("Will abort if system malloc() and friends fail\n"); 168 } 169 } 170 } 171 172 /** 173 * Whether to turn off mem pools, useful for leak checking. 174 * 175 * @returns #TRUE if mempools should not be used. 176 */ 177 dbus_bool_t 178 _dbus_disable_mem_pools (void) 179 { 180 _dbus_initialize_malloc_debug (); 181 return disable_mem_pools; 182 } 183 184 /** 185 * Sets the number of allocations until we simulate a failed 186 * allocation. If set to 0, the next allocation to run 187 * fails; if set to 1, one succeeds then the next fails; etc. 188 * Set to _DBUS_INT_MAX to not fail anything. 189 * 190 * @param until_next_fail number of successful allocs before one fails 191 */ 192 void 193 _dbus_set_fail_alloc_counter (int until_next_fail) 194 { 195 _dbus_initialize_malloc_debug (); 196 197 fail_alloc_counter = until_next_fail; 198 199 #if 0 200 _dbus_verbose ("Set fail alloc counter = %d\n", fail_alloc_counter); 201 #endif 202 } 203 204 /** 205 * Gets the number of successful allocs until we'll simulate 206 * a failed alloc. 207 * 208 * @returns current counter value 209 */ 210 int 211 _dbus_get_fail_alloc_counter (void) 212 { 213 _dbus_initialize_malloc_debug (); 214 215 return fail_alloc_counter; 216 } 217 218 /** 219 * Sets how many mallocs to fail when the fail alloc counter reaches 220 * 0. 221 * 222 * @param failures_per_failure number to fail 223 */ 224 void 225 _dbus_set_fail_alloc_failures (int failures_per_failure) 226 { 227 n_failures_per_failure = failures_per_failure; 228 } 229 230 /** 231 * Gets the number of failures we'll have when the fail malloc 232 * counter reaches 0. 233 * 234 * @returns number of failures planned 235 */ 236 int 237 _dbus_get_fail_alloc_failures (void) 238 { 239 return n_failures_per_failure; 240 } 241 242 #ifdef DBUS_BUILD_TESTS 243 /** 244 * Called when about to alloc some memory; if 245 * it returns #TRUE, then the allocation should 246 * fail. If it returns #FALSE, then the allocation 247 * should not fail. 248 * 249 * @returns #TRUE if this alloc should fail 250 */ 251 dbus_bool_t 252 _dbus_decrement_fail_alloc_counter (void) 253 { 254 _dbus_initialize_malloc_debug (); 255 #ifdef DBUS_WIN_FIXME 256 { 257 static dbus_bool_t called = 0; 258 259 if (!called) 260 { 261 _dbus_verbose("TODO: memory allocation testing errors disabled for now\n"); 262 called = 1; 263 } 264 return FALSE; 265 } 266 #endif 267 268 if (fail_alloc_counter <= 0) 269 { 270 if (backtrace_on_fail_alloc) 271 _dbus_print_backtrace (); 272 273 _dbus_verbose ("failure %d\n", n_failures_this_failure); 274 275 n_failures_this_failure += 1; 276 if (n_failures_this_failure >= n_failures_per_failure) 277 { 278 if (fail_nth >= 0) 279 fail_alloc_counter = fail_nth; 280 else 281 fail_alloc_counter = _DBUS_INT_MAX; 282 283 n_failures_this_failure = 0; 284 285 _dbus_verbose ("reset fail alloc counter to %d\n", fail_alloc_counter); 286 } 287 288 return TRUE; 289 } 290 else 291 { 292 fail_alloc_counter -= 1; 293 return FALSE; 294 } 295 } 296 #endif /* DBUS_BUILD_TESTS */ 297 298 /** 299 * Get the number of outstanding malloc()'d blocks. 300 * 301 * @returns number of blocks 302 */ 303 int 304 _dbus_get_malloc_blocks_outstanding (void) 305 { 306 return _dbus_atomic_get (&n_blocks_outstanding); 307 } 308 309 /** 310 * Where the block came from. 311 */ 312 typedef enum 313 { 314 SOURCE_UNKNOWN, 315 SOURCE_MALLOC, 316 SOURCE_REALLOC, 317 SOURCE_MALLOC_ZERO, 318 SOURCE_REALLOC_NULL 319 } BlockSource; 320 321 static const char* 322 source_string (BlockSource source) 323 { 324 switch (source) 325 { 326 case SOURCE_UNKNOWN: 327 return "unknown"; 328 case SOURCE_MALLOC: 329 return "malloc"; 330 case SOURCE_REALLOC: 331 return "realloc"; 332 case SOURCE_MALLOC_ZERO: 333 return "malloc0"; 334 case SOURCE_REALLOC_NULL: 335 return "realloc(NULL)"; 336 } 337 _dbus_assert_not_reached ("Invalid malloc block source ID"); 338 return "invalid!"; 339 } 340 341 static void 342 check_guards (void *free_block, 343 dbus_bool_t overwrite) 344 { 345 if (free_block != NULL) 346 { 347 unsigned char *block = ((unsigned char*)free_block) - GUARD_START_OFFSET; 348 size_t requested_bytes = *(dbus_uint32_t*)block; 349 BlockSource source = *(dbus_uint32_t*)(block + 4); 350 unsigned int i; 351 dbus_bool_t failed; 352 353 failed = FALSE; 354 355 #if 0 356 _dbus_verbose ("Checking %d bytes request from source %s\n", 357 requested_bytes, source_string (source)); 358 #endif 359 360 i = GUARD_INFO_SIZE; 361 while (i < GUARD_START_OFFSET) 362 { 363 dbus_uint32_t value = *(dbus_uint32_t*) &block[i]; 364 if (value != GUARD_VALUE) 365 { 366 _dbus_warn ("Block of %lu bytes from %s had start guard value 0x%ux at %d expected 0x%x\n", 367 (long) requested_bytes, source_string (source), 368 value, i, GUARD_VALUE); 369 failed = TRUE; 370 } 371 372 i += 4; 373 } 374 375 i = GUARD_START_OFFSET + requested_bytes; 376 while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD)) 377 { 378 dbus_uint32_t value = *(dbus_uint32_t*) &block[i]; 379 if (value != GUARD_VALUE) 380 { 381 _dbus_warn ("Block of %lu bytes from %s had end guard value 0x%ux at %d expected 0x%x\n", 382 (long) requested_bytes, source_string (source), 383 value, i, GUARD_VALUE); 384 failed = TRUE; 385 } 386 387 i += 4; 388 } 389 390 /* set memory to anything but nul bytes */ 391 if (overwrite) 392 memset (free_block, 'g', requested_bytes); 393 394 if (failed) 395 _dbus_assert_not_reached ("guard value corruption"); 396 } 397 } 398 399 static void* 400 set_guards (void *real_block, 401 size_t requested_bytes, 402 BlockSource source) 403 { 404 unsigned char *block = real_block; 405 unsigned int i; 406 407 if (block == NULL) 408 return NULL; 409 410 _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE); 411 412 *((dbus_uint32_t*)block) = requested_bytes; 413 *((dbus_uint32_t*)(block + 4)) = source; 414 415 i = GUARD_INFO_SIZE; 416 while (i < GUARD_START_OFFSET) 417 { 418 (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE; 419 420 i += 4; 421 } 422 423 i = GUARD_START_OFFSET + requested_bytes; 424 while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD)) 425 { 426 (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE; 427 428 i += 4; 429 } 430 431 check_guards (block + GUARD_START_OFFSET, FALSE); 432 433 return block + GUARD_START_OFFSET; 434 } 435 436 #endif 437 438 /** @} */ /* End of internals docs */ 439 440 441 /** 442 * @addtogroup DBusMemory 443 * 444 * @{ 445 */ 446 447 /** 448 * Allocates the given number of bytes, as with standard 449 * malloc(). Guaranteed to return #NULL if bytes is zero 450 * on all platforms. Returns #NULL if the allocation fails. 451 * The memory must be released with dbus_free(). 452 * 453 * dbus_malloc() memory is NOT safe to free with regular free() from 454 * the C library. Free it with dbus_free() only. 455 * 456 * @param bytes number of bytes to allocate 457 * @return allocated memory, or #NULL if the allocation fails. 458 */ 459 void* 460 dbus_malloc (size_t bytes) 461 { 462 #ifdef DBUS_BUILD_TESTS 463 _dbus_initialize_malloc_debug (); 464 465 if (_dbus_decrement_fail_alloc_counter ()) 466 { 467 _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes); 468 return NULL; 469 } 470 #endif 471 472 if (bytes == 0) /* some system mallocs handle this, some don't */ 473 return NULL; 474 #ifdef DBUS_BUILD_TESTS 475 else if (fail_size != 0 && bytes > fail_size) 476 return NULL; 477 else if (guards) 478 { 479 void *block; 480 481 block = malloc (bytes + GUARD_EXTRA_SIZE); 482 if (block) 483 { 484 _dbus_atomic_inc (&n_blocks_outstanding); 485 } 486 else if (malloc_cannot_fail) 487 { 488 _dbus_warn ("out of memory: malloc (%ld + %ld)\n", 489 (long) bytes, (long) GUARD_EXTRA_SIZE); 490 _dbus_abort (); 491 } 492 493 return set_guards (block, bytes, SOURCE_MALLOC); 494 } 495 #endif 496 else 497 { 498 void *mem; 499 mem = malloc (bytes); 500 501 #ifdef DBUS_BUILD_TESTS 502 if (mem) 503 { 504 _dbus_atomic_inc (&n_blocks_outstanding); 505 } 506 else if (malloc_cannot_fail) 507 { 508 _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); 509 _dbus_abort (); 510 } 511 #endif 512 513 return mem; 514 } 515 } 516 517 /** 518 * Allocates the given number of bytes, as with standard malloc(), but 519 * all bytes are initialized to zero as with calloc(). Guaranteed to 520 * return #NULL if bytes is zero on all platforms. Returns #NULL if the 521 * allocation fails. The memory must be released with dbus_free(). 522 * 523 * dbus_malloc0() memory is NOT safe to free with regular free() from 524 * the C library. Free it with dbus_free() only. 525 * 526 * @param bytes number of bytes to allocate 527 * @return allocated memory, or #NULL if the allocation fails. 528 */ 529 void* 530 dbus_malloc0 (size_t bytes) 531 { 532 #ifdef DBUS_BUILD_TESTS 533 _dbus_initialize_malloc_debug (); 534 535 if (_dbus_decrement_fail_alloc_counter ()) 536 { 537 _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes); 538 539 return NULL; 540 } 541 #endif 542 543 if (bytes == 0) 544 return NULL; 545 #ifdef DBUS_BUILD_TESTS 546 else if (fail_size != 0 && bytes > fail_size) 547 return NULL; 548 else if (guards) 549 { 550 void *block; 551 552 block = calloc (bytes + GUARD_EXTRA_SIZE, 1); 553 554 if (block) 555 { 556 _dbus_atomic_inc (&n_blocks_outstanding); 557 } 558 else if (malloc_cannot_fail) 559 { 560 _dbus_warn ("out of memory: calloc (%ld + %ld, 1)\n", 561 (long) bytes, (long) GUARD_EXTRA_SIZE); 562 _dbus_abort (); 563 } 564 565 return set_guards (block, bytes, SOURCE_MALLOC_ZERO); 566 } 567 #endif 568 else 569 { 570 void *mem; 571 mem = calloc (bytes, 1); 572 573 #ifdef DBUS_BUILD_TESTS 574 if (mem) 575 { 576 _dbus_atomic_inc (&n_blocks_outstanding); 577 } 578 else if (malloc_cannot_fail) 579 { 580 _dbus_warn ("out of memory: calloc (%ld)\n", (long) bytes); 581 _dbus_abort (); 582 } 583 #endif 584 585 return mem; 586 } 587 } 588 589 /** 590 * Resizes a block of memory previously allocated by dbus_malloc() or 591 * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes 592 * is zero on all platforms. Returns #NULL if the resize fails. 593 * If the resize fails, the memory is not freed. 594 * 595 * @param memory block to be resized 596 * @param bytes new size of the memory block 597 * @return allocated memory, or #NULL if the resize fails. 598 */ 599 void* 600 dbus_realloc (void *memory, 601 size_t bytes) 602 { 603 #ifdef DBUS_BUILD_TESTS 604 _dbus_initialize_malloc_debug (); 605 606 if (_dbus_decrement_fail_alloc_counter ()) 607 { 608 _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes); 609 610 return NULL; 611 } 612 #endif 613 614 if (bytes == 0) /* guarantee this is safe */ 615 { 616 dbus_free (memory); 617 return NULL; 618 } 619 #ifdef DBUS_BUILD_TESTS 620 else if (fail_size != 0 && bytes > fail_size) 621 return NULL; 622 else if (guards) 623 { 624 if (memory) 625 { 626 size_t old_bytes; 627 void *block; 628 629 check_guards (memory, FALSE); 630 631 block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET, 632 bytes + GUARD_EXTRA_SIZE); 633 634 if (block == NULL) 635 { 636 if (malloc_cannot_fail) 637 { 638 _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n", 639 memory, (long) bytes, (long) GUARD_EXTRA_SIZE); 640 _dbus_abort (); 641 } 642 643 return NULL; 644 } 645 646 old_bytes = *(dbus_uint32_t*)block; 647 if (bytes >= old_bytes) 648 /* old guards shouldn't have moved */ 649 check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE); 650 651 return set_guards (block, bytes, SOURCE_REALLOC); 652 } 653 else 654 { 655 void *block; 656 657 block = malloc (bytes + GUARD_EXTRA_SIZE); 658 659 if (block) 660 { 661 _dbus_atomic_inc (&n_blocks_outstanding); 662 } 663 else if (malloc_cannot_fail) 664 { 665 _dbus_warn ("out of memory: malloc (%ld + %ld)\n", 666 (long) bytes, (long) GUARD_EXTRA_SIZE); 667 _dbus_abort (); 668 } 669 670 return set_guards (block, bytes, SOURCE_REALLOC_NULL); 671 } 672 } 673 #endif 674 else 675 { 676 void *mem; 677 mem = realloc (memory, bytes); 678 679 #ifdef DBUS_BUILD_TESTS 680 if (mem == NULL && malloc_cannot_fail) 681 { 682 _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); 683 _dbus_abort (); 684 } 685 686 if (memory == NULL && mem != NULL) 687 _dbus_atomic_inc (&n_blocks_outstanding); 688 #endif 689 return mem; 690 } 691 } 692 693 /** 694 * Frees a block of memory previously allocated by dbus_malloc() or 695 * dbus_malloc0(). If passed #NULL, does nothing. 696 * 697 * @param memory block to be freed 698 */ 699 void 700 dbus_free (void *memory) 701 { 702 #ifdef DBUS_BUILD_TESTS 703 if (guards) 704 { 705 check_guards (memory, TRUE); 706 if (memory) 707 { 708 #ifdef DBUS_DISABLE_ASSERT 709 _dbus_atomic_dec (&n_blocks_outstanding); 710 #else 711 dbus_int32_t old_value; 712 713 old_value = _dbus_atomic_dec (&n_blocks_outstanding); 714 _dbus_assert (old_value >= 1); 715 #endif 716 717 free (((unsigned char*)memory) - GUARD_START_OFFSET); 718 } 719 720 return; 721 } 722 #endif 723 724 if (memory) /* we guarantee it's safe to free (NULL) */ 725 { 726 #ifdef DBUS_BUILD_TESTS 727 #ifdef DBUS_DISABLE_ASSERT 728 _dbus_atomic_dec (&n_blocks_outstanding); 729 #else 730 dbus_int32_t old_value; 731 732 old_value = _dbus_atomic_dec (&n_blocks_outstanding); 733 _dbus_assert (old_value >= 1); 734 #endif 735 #endif 736 737 free (memory); 738 } 739 } 740 741 /** 742 * Frees a #NULL-terminated array of strings. 743 * If passed #NULL, does nothing. 744 * 745 * @param str_array the array to be freed 746 */ 747 void 748 dbus_free_string_array (char **str_array) 749 { 750 if (str_array) 751 { 752 int i; 753 754 i = 0; 755 while (str_array[i]) 756 { 757 dbus_free (str_array[i]); 758 i++; 759 } 760 761 dbus_free (str_array); 762 } 763 } 764 765 /** @} */ /* End of public API docs block */ 766 767 768 /** 769 * @addtogroup DBusMemoryInternals 770 * 771 * @{ 772 */ 773 774 /** 775 * _dbus_current_generation is used to track each 776 * time that dbus_shutdown() is called, so we can 777 * reinit things after it's been called. It is simply 778 * incremented each time we shut down. 779 */ 780 int _dbus_current_generation = 1; 781 782 /** 783 * Represents a function to be called on shutdown. 784 */ 785 typedef struct ShutdownClosure ShutdownClosure; 786 787 /** 788 * This struct represents a function to be called on shutdown. 789 */ 790 struct ShutdownClosure 791 { 792 ShutdownClosure *next; /**< Next ShutdownClosure */ 793 DBusShutdownFunction func; /**< Function to call */ 794 void *data; /**< Data for function */ 795 }; 796 797 _DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs); 798 static ShutdownClosure *registered_globals = NULL; 799 800 /** 801 * Register a cleanup function to be called exactly once 802 * the next time dbus_shutdown() is called. 803 * 804 * @param func the function 805 * @param data data to pass to the function 806 * @returns #FALSE on not enough memory 807 */ 808 dbus_bool_t 809 _dbus_register_shutdown_func (DBusShutdownFunction func, 810 void *data) 811 { 812 ShutdownClosure *c; 813 814 c = dbus_new (ShutdownClosure, 1); 815 816 if (c == NULL) 817 return FALSE; 818 819 c->func = func; 820 c->data = data; 821 822 _DBUS_LOCK (shutdown_funcs); 823 824 c->next = registered_globals; 825 registered_globals = c; 826 827 _DBUS_UNLOCK (shutdown_funcs); 828 829 return TRUE; 830 } 831 832 /** @} */ /* End of private API docs block */ 833 834 835 /** 836 * @addtogroup DBusMemory 837 * 838 * @{ 839 */ 840 841 /** 842 * Frees all memory allocated internally by libdbus and 843 * reverses the effects of dbus_threads_init(). libdbus keeps internal 844 * global variables, for example caches and thread locks, and it 845 * can be useful to free these internal data structures. 846 * 847 * dbus_shutdown() does NOT free memory that was returned 848 * to the application. It only returns libdbus-internal 849 * data structures. 850 * 851 * You MUST free all memory and release all reference counts 852 * returned to you by libdbus prior to calling dbus_shutdown(). 853 * 854 * You can't continue to use any D-Bus objects, such as connections, 855 * that were allocated prior to dbus_shutdown(). You can, however, 856 * start over; call dbus_threads_init() again, create new connections, 857 * and so forth. 858 * 859 * WARNING: dbus_shutdown() is NOT thread safe, it must be called 860 * while NO other threads are using D-Bus. (Remember, you have to free 861 * all D-Bus objects and memory before you call dbus_shutdown(), so no 862 * thread can be using libdbus.) 863 * 864 * The purpose of dbus_shutdown() is to allow applications to get 865 * clean output from memory leak checkers. dbus_shutdown() may also be 866 * useful if you want to dlopen() libdbus instead of linking to it, 867 * and want to be able to unload the library again. 868 * 869 * There is absolutely no requirement to call dbus_shutdown() - in fact, 870 * most applications won't bother and should not feel guilty. 871 * 872 * You have to know that nobody is using libdbus in your application's 873 * process before you can call dbus_shutdown(). One implication of this 874 * is that calling dbus_shutdown() from a library is almost certainly 875 * wrong, since you don't know what the rest of the app is up to. 876 * 877 */ 878 void 879 dbus_shutdown (void) 880 { 881 while (registered_globals != NULL) 882 { 883 ShutdownClosure *c; 884 885 c = registered_globals; 886 registered_globals = c->next; 887 888 (* c->func) (c->data); 889 890 dbus_free (c); 891 } 892 893 _dbus_current_generation += 1; 894 } 895 896 /** @} */ /** End of public API docs block */ 897 898 #ifdef DBUS_BUILD_TESTS 899 #include "dbus-test.h" 900 901 /** 902 * @ingroup DBusMemoryInternals 903 * Unit test for DBusMemory 904 * @returns #TRUE on success. 905 */ 906 dbus_bool_t 907 _dbus_memory_test (void) 908 { 909 dbus_bool_t old_guards; 910 void *p; 911 size_t size; 912 913 old_guards = guards; 914 guards = TRUE; 915 p = dbus_malloc (4); 916 if (p == NULL) 917 _dbus_assert_not_reached ("no memory"); 918 for (size = 4; size < 256; size += 4) 919 { 920 p = dbus_realloc (p, size); 921 if (p == NULL) 922 _dbus_assert_not_reached ("no memory"); 923 } 924 for (size = 256; size != 0; size -= 4) 925 { 926 p = dbus_realloc (p, size); 927 if (p == NULL) 928 _dbus_assert_not_reached ("no memory"); 929 } 930 dbus_free (p); 931 guards = old_guards; 932 return TRUE; 933 } 934 935 #endif 936