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