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
100static dbus_bool_t debug_initialized = FALSE;
101static int fail_nth = -1;
102static size_t fail_size = 0;
103static int fail_alloc_counter = _DBUS_INT_MAX;
104static int n_failures_per_failure = 1;
105static int n_failures_this_failure = 0;
106static dbus_bool_t guards = FALSE;
107static dbus_bool_t disable_mem_pools = FALSE;
108static dbus_bool_t backtrace_on_fail_alloc = FALSE;
109static dbus_bool_t malloc_cannot_fail = FALSE;
110static 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
125static 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 */
177dbus_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 */
192void
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 */
210int
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 */
224void
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 */
236int
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 */
251dbus_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 */
303int
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 */
312typedef enum
313{
314  SOURCE_UNKNOWN,
315  SOURCE_MALLOC,
316  SOURCE_REALLOC,
317  SOURCE_MALLOC_ZERO,
318  SOURCE_REALLOC_NULL
319} BlockSource;
320
321static const char*
322source_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
341static void
342check_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
399static void*
400set_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 */
459void*
460dbus_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 */
529void*
530dbus_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 */
599void*
600dbus_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 */
699void
700dbus_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 */
747void
748dbus_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 */
780int _dbus_current_generation = 1;
781
782/**
783 * Represents a function to be called on shutdown.
784 */
785typedef struct ShutdownClosure ShutdownClosure;
786
787/**
788 * This struct represents a function to be called on shutdown.
789 */
790struct 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);
798static 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 */
808dbus_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 */
878void
879dbus_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 */
906dbus_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