Home | History | Annotate | Download | only in dbus
      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 DBusAtomic n_blocks_outstanding = {0};
    110 
    111 /** value stored in guard padding for debugging buffer overrun */
    112 #define GUARD_VALUE 0xdeadbeef
    113 /** size of the information about the block stored in guard mode */
    114 #define GUARD_INFO_SIZE 8
    115 /** size of the GUARD_VALUE-filled padding after the header info  */
    116 #define GUARD_START_PAD 16
    117 /** size of the GUARD_VALUE-filled padding at the end of the block */
    118 #define GUARD_END_PAD 16
    119 /** size of stuff at start of block */
    120 #define GUARD_START_OFFSET (GUARD_START_PAD + GUARD_INFO_SIZE)
    121 /** total extra size over the requested allocation for guard stuff */
    122 #define GUARD_EXTRA_SIZE (GUARD_START_OFFSET + GUARD_END_PAD)
    123 
    124 static void
    125 _dbus_initialize_malloc_debug (void)
    126 {
    127   if (!debug_initialized)
    128     {
    129       debug_initialized = TRUE;
    130 
    131       if (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH") != NULL)
    132 	{
    133 	  fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH"));
    134           fail_alloc_counter = fail_nth;
    135           _dbus_verbose ("Will fail malloc every %d times\n", fail_nth);
    136 	}
    137 
    138       if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL)
    139         {
    140           fail_size = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN"));
    141           _dbus_verbose ("Will fail mallocs over %ld bytes\n",
    142                          (long) fail_size);
    143         }
    144 
    145       if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL)
    146         {
    147           guards = TRUE;
    148           _dbus_verbose ("Will use malloc guards\n");
    149         }
    150 
    151       if (_dbus_getenv ("DBUS_DISABLE_MEM_POOLS") != NULL)
    152         {
    153           disable_mem_pools = TRUE;
    154           _dbus_verbose ("Will disable memory pools\n");
    155         }
    156 
    157       if (_dbus_getenv ("DBUS_MALLOC_BACKTRACES") != NULL)
    158         {
    159           backtrace_on_fail_alloc = TRUE;
    160           _dbus_verbose ("Will backtrace on failing a malloc\n");
    161         }
    162     }
    163 }
    164 
    165 /**
    166  * Whether to turn off mem pools, useful for leak checking.
    167  *
    168  * @returns #TRUE if mempools should not be used.
    169  */
    170 dbus_bool_t
    171 _dbus_disable_mem_pools (void)
    172 {
    173   _dbus_initialize_malloc_debug ();
    174   return disable_mem_pools;
    175 }
    176 
    177 /**
    178  * Sets the number of allocations until we simulate a failed
    179  * allocation. If set to 0, the next allocation to run
    180  * fails; if set to 1, one succeeds then the next fails; etc.
    181  * Set to _DBUS_INT_MAX to not fail anything.
    182  *
    183  * @param until_next_fail number of successful allocs before one fails
    184  */
    185 void
    186 _dbus_set_fail_alloc_counter (int until_next_fail)
    187 {
    188   _dbus_initialize_malloc_debug ();
    189 
    190   fail_alloc_counter = until_next_fail;
    191 
    192 #if 0
    193   _dbus_verbose ("Set fail alloc counter = %d\n", fail_alloc_counter);
    194 #endif
    195 }
    196 
    197 /**
    198  * Gets the number of successful allocs until we'll simulate
    199  * a failed alloc.
    200  *
    201  * @returns current counter value
    202  */
    203 int
    204 _dbus_get_fail_alloc_counter (void)
    205 {
    206   _dbus_initialize_malloc_debug ();
    207 
    208   return fail_alloc_counter;
    209 }
    210 
    211 /**
    212  * Sets how many mallocs to fail when the fail alloc counter reaches
    213  * 0.
    214  *
    215  * @param failures_per_failure number to fail
    216  */
    217 void
    218 _dbus_set_fail_alloc_failures (int failures_per_failure)
    219 {
    220   n_failures_per_failure = failures_per_failure;
    221 }
    222 
    223 /**
    224  * Gets the number of failures we'll have when the fail malloc
    225  * counter reaches 0.
    226  *
    227  * @returns number of failures planned
    228  */
    229 int
    230 _dbus_get_fail_alloc_failures (void)
    231 {
    232   return n_failures_per_failure;
    233 }
    234 
    235 #ifdef DBUS_BUILD_TESTS
    236 static dbus_bool_t called = 0;
    237 /**
    238  * Called when about to alloc some memory; if
    239  * it returns #TRUE, then the allocation should
    240  * fail. If it returns #FALSE, then the allocation
    241  * should not fail.
    242  *
    243  * @returns #TRUE if this alloc should fail
    244  */
    245 dbus_bool_t
    246 _dbus_decrement_fail_alloc_counter (void)
    247 {
    248   _dbus_initialize_malloc_debug ();
    249 #ifdef DBUS_WIN_FIXME
    250   {
    251     if (!called)
    252       {
    253         _dbus_verbose("TODO: memory allocation testing errors disabled for now\n");
    254         called = 1;
    255       }
    256     return FALSE;
    257   }
    258 #endif
    259 
    260   if (fail_alloc_counter <= 0)
    261     {
    262       if (backtrace_on_fail_alloc)
    263         _dbus_print_backtrace ();
    264 
    265       _dbus_verbose ("failure %d\n", n_failures_this_failure);
    266 
    267       n_failures_this_failure += 1;
    268       if (n_failures_this_failure >= n_failures_per_failure)
    269         {
    270           if (fail_nth >= 0)
    271             fail_alloc_counter = fail_nth;
    272           else
    273             fail_alloc_counter = _DBUS_INT_MAX;
    274 
    275           n_failures_this_failure = 0;
    276 
    277           _dbus_verbose ("reset fail alloc counter to %d\n", fail_alloc_counter);
    278         }
    279 
    280       return TRUE;
    281     }
    282   else
    283     {
    284       fail_alloc_counter -= 1;
    285       return FALSE;
    286     }
    287 }
    288 #endif /* DBUS_BUILD_TESTS */
    289 
    290 /**
    291  * Get the number of outstanding malloc()'d blocks.
    292  *
    293  * @returns number of blocks
    294  */
    295 int
    296 _dbus_get_malloc_blocks_outstanding (void)
    297 {
    298   return n_blocks_outstanding.value;
    299 }
    300 
    301 /**
    302  * Where the block came from.
    303  */
    304 typedef enum
    305 {
    306   SOURCE_UNKNOWN,
    307   SOURCE_MALLOC,
    308   SOURCE_REALLOC,
    309   SOURCE_MALLOC_ZERO,
    310   SOURCE_REALLOC_NULL
    311 } BlockSource;
    312 
    313 static const char*
    314 source_string (BlockSource source)
    315 {
    316   switch (source)
    317     {
    318     case SOURCE_UNKNOWN:
    319       return "unknown";
    320     case SOURCE_MALLOC:
    321       return "malloc";
    322     case SOURCE_REALLOC:
    323       return "realloc";
    324     case SOURCE_MALLOC_ZERO:
    325       return "malloc0";
    326     case SOURCE_REALLOC_NULL:
    327       return "realloc(NULL)";
    328     }
    329   _dbus_assert_not_reached ("Invalid malloc block source ID");
    330   return "invalid!";
    331 }
    332 
    333 static void
    334 check_guards (void       *free_block,
    335               dbus_bool_t overwrite)
    336 {
    337   if (free_block != NULL)
    338     {
    339       unsigned char *block = ((unsigned char*)free_block) - GUARD_START_OFFSET;
    340       size_t requested_bytes = *(dbus_uint32_t*)block;
    341       BlockSource source = *(dbus_uint32_t*)(block + 4);
    342       unsigned int i;
    343       dbus_bool_t failed;
    344 
    345       failed = FALSE;
    346 
    347 #if 0
    348       _dbus_verbose ("Checking %d bytes request from source %s\n",
    349                      requested_bytes, source_string (source));
    350 #endif
    351 
    352       i = GUARD_INFO_SIZE;
    353       while (i < GUARD_START_OFFSET)
    354         {
    355           dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
    356           if (value != GUARD_VALUE)
    357             {
    358               _dbus_warn ("Block of %lu bytes from %s had start guard value 0x%ux at %d expected 0x%x\n",
    359                           (long) requested_bytes, source_string (source),
    360                           value, i, GUARD_VALUE);
    361               failed = TRUE;
    362             }
    363 
    364           i += 4;
    365         }
    366 
    367       i = GUARD_START_OFFSET + requested_bytes;
    368       while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
    369         {
    370           dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
    371           if (value != GUARD_VALUE)
    372             {
    373               _dbus_warn ("Block of %lu bytes from %s had end guard value 0x%ux at %d expected 0x%x\n",
    374                           (long) requested_bytes, source_string (source),
    375                           value, i, GUARD_VALUE);
    376               failed = TRUE;
    377             }
    378 
    379           i += 4;
    380         }
    381 
    382       /* set memory to anything but nul bytes */
    383       if (overwrite)
    384         memset (free_block, 'g', requested_bytes);
    385 
    386       if (failed)
    387         _dbus_assert_not_reached ("guard value corruption");
    388     }
    389 }
    390 
    391 static void*
    392 set_guards (void       *real_block,
    393             size_t      requested_bytes,
    394             BlockSource source)
    395 {
    396   unsigned char *block = real_block;
    397   unsigned int i;
    398 
    399   if (block == NULL)
    400     return NULL;
    401 
    402   _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE);
    403 
    404   *((dbus_uint32_t*)block) = requested_bytes;
    405   *((dbus_uint32_t*)(block + 4)) = source;
    406 
    407   i = GUARD_INFO_SIZE;
    408   while (i < GUARD_START_OFFSET)
    409     {
    410       (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
    411 
    412       i += 4;
    413     }
    414 
    415   i = GUARD_START_OFFSET + requested_bytes;
    416   while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
    417     {
    418       (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
    419 
    420       i += 4;
    421     }
    422 
    423   check_guards (block + GUARD_START_OFFSET, FALSE);
    424 
    425   return block + GUARD_START_OFFSET;
    426 }
    427 
    428 #endif
    429 
    430 /** @} */ /* End of internals docs */
    431 
    432 
    433 /**
    434  * @addtogroup DBusMemory
    435  *
    436  * @{
    437  */
    438 
    439 /**
    440  * Allocates the given number of bytes, as with standard
    441  * malloc(). Guaranteed to return #NULL if bytes is zero
    442  * on all platforms. Returns #NULL if the allocation fails.
    443  * The memory must be released with dbus_free().
    444  *
    445  * dbus_malloc() memory is NOT safe to free with regular free() from
    446  * the C library. Free it with dbus_free() only.
    447  *
    448  * @param bytes number of bytes to allocate
    449  * @return allocated memory, or #NULL if the allocation fails.
    450  */
    451 void*
    452 dbus_malloc (size_t bytes)
    453 {
    454 #ifdef DBUS_BUILD_TESTS
    455   _dbus_initialize_malloc_debug ();
    456 
    457   if (_dbus_decrement_fail_alloc_counter ())
    458     {
    459       _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes);
    460       return NULL;
    461     }
    462 #endif
    463 
    464   if (bytes == 0) /* some system mallocs handle this, some don't */
    465     return NULL;
    466 #ifdef DBUS_BUILD_TESTS
    467   else if (fail_size != 0 && bytes > fail_size)
    468     return NULL;
    469   else if (guards)
    470     {
    471       void *block;
    472 
    473       block = malloc (bytes + GUARD_EXTRA_SIZE);
    474       if (block)
    475 	_dbus_atomic_inc (&n_blocks_outstanding);
    476 
    477       return set_guards (block, bytes, SOURCE_MALLOC);
    478     }
    479 #endif
    480   else
    481     {
    482       void *mem;
    483       mem = malloc (bytes);
    484 #ifdef DBUS_BUILD_TESTS
    485       if (mem)
    486 	_dbus_atomic_inc (&n_blocks_outstanding);
    487 #endif
    488       return mem;
    489     }
    490 }
    491 
    492 /**
    493  * Allocates the given number of bytes, as with standard malloc(), but
    494  * all bytes are initialized to zero as with calloc(). Guaranteed to
    495  * return #NULL if bytes is zero on all platforms. Returns #NULL if the
    496  * allocation fails.  The memory must be released with dbus_free().
    497  *
    498  * dbus_malloc0() memory is NOT safe to free with regular free() from
    499  * the C library. Free it with dbus_free() only.
    500  *
    501  * @param bytes number of bytes to allocate
    502  * @return allocated memory, or #NULL if the allocation fails.
    503  */
    504 void*
    505 dbus_malloc0 (size_t bytes)
    506 {
    507 #ifdef DBUS_BUILD_TESTS
    508   _dbus_initialize_malloc_debug ();
    509 
    510   if (_dbus_decrement_fail_alloc_counter ())
    511     {
    512       _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes);
    513 
    514       return NULL;
    515     }
    516 #endif
    517 
    518   if (bytes == 0)
    519     return NULL;
    520 #ifdef DBUS_BUILD_TESTS
    521   else if (fail_size != 0 && bytes > fail_size)
    522     return NULL;
    523   else if (guards)
    524     {
    525       void *block;
    526 
    527       block = calloc (bytes + GUARD_EXTRA_SIZE, 1);
    528       if (block)
    529 	_dbus_atomic_inc (&n_blocks_outstanding);
    530       return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
    531     }
    532 #endif
    533   else
    534     {
    535       void *mem;
    536       mem = calloc (bytes, 1);
    537 #ifdef DBUS_BUILD_TESTS
    538       if (mem)
    539 	_dbus_atomic_inc (&n_blocks_outstanding);
    540 #endif
    541       return mem;
    542     }
    543 }
    544 
    545 /**
    546  * Resizes a block of memory previously allocated by dbus_malloc() or
    547  * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes
    548  * is zero on all platforms. Returns #NULL if the resize fails.
    549  * If the resize fails, the memory is not freed.
    550  *
    551  * @param memory block to be resized
    552  * @param bytes new size of the memory block
    553  * @return allocated memory, or #NULL if the resize fails.
    554  */
    555 void*
    556 dbus_realloc (void  *memory,
    557               size_t bytes)
    558 {
    559 #ifdef DBUS_BUILD_TESTS
    560   _dbus_initialize_malloc_debug ();
    561 
    562   if (_dbus_decrement_fail_alloc_counter ())
    563     {
    564       _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes);
    565 
    566       return NULL;
    567     }
    568 #endif
    569 
    570   if (bytes == 0) /* guarantee this is safe */
    571     {
    572       dbus_free (memory);
    573       return NULL;
    574     }
    575 #ifdef DBUS_BUILD_TESTS
    576   else if (fail_size != 0 && bytes > fail_size)
    577     return NULL;
    578   else if (guards)
    579     {
    580       if (memory)
    581         {
    582           size_t old_bytes;
    583           void *block;
    584 
    585           check_guards (memory, FALSE);
    586 
    587           block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
    588                            bytes + GUARD_EXTRA_SIZE);
    589 
    590 	  old_bytes = *(dbus_uint32_t*)block;
    591           if (block && bytes >= old_bytes)
    592             /* old guards shouldn't have moved */
    593             check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE);
    594 
    595           return set_guards (block, bytes, SOURCE_REALLOC);
    596         }
    597       else
    598         {
    599           void *block;
    600 
    601           block = malloc (bytes + GUARD_EXTRA_SIZE);
    602 
    603           if (block)
    604 	    _dbus_atomic_inc (&n_blocks_outstanding);
    605 
    606           return set_guards (block, bytes, SOURCE_REALLOC_NULL);
    607         }
    608     }
    609 #endif
    610   else
    611     {
    612       void *mem;
    613       mem = realloc (memory, bytes);
    614 #ifdef DBUS_BUILD_TESTS
    615       if (memory == NULL && mem != NULL)
    616 	    _dbus_atomic_inc (&n_blocks_outstanding);
    617 #endif
    618       return mem;
    619     }
    620 }
    621 
    622 /**
    623  * Frees a block of memory previously allocated by dbus_malloc() or
    624  * dbus_malloc0(). If passed #NULL, does nothing.
    625  *
    626  * @param memory block to be freed
    627  */
    628 void
    629 dbus_free (void  *memory)
    630 {
    631 #ifdef DBUS_BUILD_TESTS
    632   if (guards)
    633     {
    634       check_guards (memory, TRUE);
    635       if (memory)
    636         {
    637 	  _dbus_atomic_dec (&n_blocks_outstanding);
    638 
    639 	  _dbus_assert (n_blocks_outstanding.value >= 0);
    640 
    641           free (((unsigned char*)memory) - GUARD_START_OFFSET);
    642         }
    643 
    644       return;
    645     }
    646 #endif
    647 
    648   if (memory) /* we guarantee it's safe to free (NULL) */
    649     {
    650 #ifdef DBUS_BUILD_TESTS
    651       _dbus_atomic_dec (&n_blocks_outstanding);
    652 
    653       _dbus_assert (n_blocks_outstanding.value >= 0);
    654 #endif
    655 
    656       free (memory);
    657     }
    658 }
    659 
    660 /**
    661  * Frees a #NULL-terminated array of strings.
    662  * If passed #NULL, does nothing.
    663  *
    664  * @param str_array the array to be freed
    665  */
    666 void
    667 dbus_free_string_array (char **str_array)
    668 {
    669   if (str_array)
    670     {
    671       int i;
    672 
    673       i = 0;
    674       while (str_array[i])
    675 	{
    676 	  dbus_free (str_array[i]);
    677 	  i++;
    678 	}
    679 
    680       dbus_free (str_array);
    681     }
    682 }
    683 
    684 /** @} */ /* End of public API docs block */
    685 
    686 
    687 /**
    688  * @addtogroup DBusMemoryInternals
    689  *
    690  * @{
    691  */
    692 
    693 /**
    694  * _dbus_current_generation is used to track each
    695  * time that dbus_shutdown() is called, so we can
    696  * reinit things after it's been called. It is simply
    697  * incremented each time we shut down.
    698  */
    699 int _dbus_current_generation = 1;
    700 
    701 /**
    702  * Represents a function to be called on shutdown.
    703  */
    704 typedef struct ShutdownClosure ShutdownClosure;
    705 
    706 /**
    707  * This struct represents a function to be called on shutdown.
    708  */
    709 struct ShutdownClosure
    710 {
    711   ShutdownClosure *next;     /**< Next ShutdownClosure */
    712   DBusShutdownFunction func; /**< Function to call */
    713   void *data;                /**< Data for function */
    714 };
    715 
    716 _DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
    717 static ShutdownClosure *registered_globals = NULL;
    718 
    719 /**
    720  * Register a cleanup function to be called exactly once
    721  * the next time dbus_shutdown() is called.
    722  *
    723  * @param func the function
    724  * @param data data to pass to the function
    725  * @returns #FALSE on not enough memory
    726  */
    727 dbus_bool_t
    728 _dbus_register_shutdown_func (DBusShutdownFunction  func,
    729                               void                 *data)
    730 {
    731   ShutdownClosure *c;
    732 
    733   c = dbus_new (ShutdownClosure, 1);
    734 
    735   if (c == NULL)
    736     return FALSE;
    737 
    738   c->func = func;
    739   c->data = data;
    740 
    741   _DBUS_LOCK (shutdown_funcs);
    742 
    743   c->next = registered_globals;
    744   registered_globals = c;
    745 
    746   _DBUS_UNLOCK (shutdown_funcs);
    747 
    748   return TRUE;
    749 }
    750 
    751 /** @} */ /* End of private API docs block */
    752 
    753 
    754 /**
    755  * @addtogroup DBusMemory
    756  *
    757  * @{
    758  */
    759 
    760 /**
    761  * Frees all memory allocated internally by libdbus and
    762  * reverses the effects of dbus_threads_init(). libdbus keeps internal
    763  * global variables, for example caches and thread locks, and it
    764  * can be useful to free these internal data structures.
    765  *
    766  * dbus_shutdown() does NOT free memory that was returned
    767  * to the application. It only returns libdbus-internal
    768  * data structures.
    769  *
    770  * You MUST free all memory and release all reference counts
    771  * returned to you by libdbus prior to calling dbus_shutdown().
    772  *
    773  * You can't continue to use any D-Bus objects, such as connections,
    774  * that were allocated prior to dbus_shutdown(). You can, however,
    775  * start over; call dbus_threads_init() again, create new connections,
    776  * and so forth.
    777  *
    778  * WARNING: dbus_shutdown() is NOT thread safe, it must be called
    779  * while NO other threads are using D-Bus. (Remember, you have to free
    780  * all D-Bus objects and memory before you call dbus_shutdown(), so no
    781  * thread can be using libdbus.)
    782  *
    783  * The purpose of dbus_shutdown() is to allow applications to get
    784  * clean output from memory leak checkers. dbus_shutdown() may also be
    785  * useful if you want to dlopen() libdbus instead of linking to it,
    786  * and want to be able to unload the library again.
    787  *
    788  * There is absolutely no requirement to call dbus_shutdown() - in fact,
    789  * most applications won't bother and should not feel guilty.
    790  *
    791  * You have to know that nobody is using libdbus in your application's
    792  * process before you can call dbus_shutdown(). One implication of this
    793  * is that calling dbus_shutdown() from a library is almost certainly
    794  * wrong, since you don't know what the rest of the app is up to.
    795  *
    796  */
    797 void
    798 dbus_shutdown (void)
    799 {
    800   while (registered_globals != NULL)
    801     {
    802       ShutdownClosure *c;
    803 
    804       c = registered_globals;
    805       registered_globals = c->next;
    806 
    807       (* c->func) (c->data);
    808 
    809       dbus_free (c);
    810     }
    811 
    812   _dbus_current_generation += 1;
    813 }
    814 
    815 /** @} */ /** End of public API docs block */
    816 
    817 #ifdef DBUS_BUILD_TESTS
    818 #include "dbus-test.h"
    819 
    820 /**
    821  * @ingroup DBusMemoryInternals
    822  * Unit test for DBusMemory
    823  * @returns #TRUE on success.
    824  */
    825 dbus_bool_t
    826 _dbus_memory_test (void)
    827 {
    828   dbus_bool_t old_guards;
    829   void *p;
    830   size_t size;
    831 
    832   old_guards = guards;
    833   guards = TRUE;
    834   p = dbus_malloc (4);
    835   if (p == NULL)
    836     _dbus_assert_not_reached ("no memory");
    837   for (size = 4; size < 256; size += 4)
    838     {
    839       p = dbus_realloc (p, size);
    840       if (p == NULL)
    841 	_dbus_assert_not_reached ("no memory");
    842     }
    843   for (size = 256; size != 0; size -= 4)
    844     {
    845       p = dbus_realloc (p, size);
    846       if (p == NULL)
    847 	_dbus_assert_not_reached ("no memory");
    848     }
    849   dbus_free (p);
    850   guards = old_guards;
    851   return TRUE;
    852 }
    853 
    854 #endif
    855