bus: Assign a serial number for messages from the driver
[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     default:
338       _dbus_assert_not_reached ("Invalid malloc block source ID");
339       return "invalid!";
340     }
341 }
342
343 static void
344 check_guards (void       *free_block,
345               dbus_bool_t overwrite)
346 {
347   if (free_block != NULL)
348     {
349       unsigned char *block = ((unsigned char*)free_block) - GUARD_START_OFFSET;
350       size_t requested_bytes = *(dbus_uint32_t*)block;
351       BlockSource source = *(dbus_uint32_t*)(block + 4);
352       unsigned int i;
353       dbus_bool_t failed;
354
355       failed = FALSE;
356
357 #if 0
358       _dbus_verbose ("Checking %d bytes request from source %s\n",
359                      requested_bytes, source_string (source));
360 #endif
361       
362       i = GUARD_INFO_SIZE;
363       while (i < GUARD_START_OFFSET)
364         {
365           dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
366           if (value != GUARD_VALUE)
367             {
368               _dbus_warn ("Block of %lu bytes from %s had start guard value 0x%ux at %d expected 0x%x",
369                           (long) requested_bytes, source_string (source),
370                           value, i, GUARD_VALUE);
371               failed = TRUE;
372             }
373           
374           i += 4;
375         }
376
377       i = GUARD_START_OFFSET + requested_bytes;
378       while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
379         {
380           dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
381           if (value != GUARD_VALUE)
382             {
383               _dbus_warn ("Block of %lu bytes from %s had end guard value 0x%ux at %d expected 0x%x",
384                           (long) requested_bytes, source_string (source),
385                           value, i, GUARD_VALUE);
386               failed = TRUE;
387             }
388           
389           i += 4;
390         }
391
392       /* set memory to anything but nul bytes */
393       if (overwrite)
394         memset (free_block, 'g', requested_bytes);
395       
396       if (failed)
397         _dbus_assert_not_reached ("guard value corruption");
398     }
399 }
400
401 static void*
402 set_guards (void       *real_block,
403             size_t      requested_bytes,
404             BlockSource source)
405 {
406   unsigned char *block = real_block;
407   unsigned int i;
408   
409   if (block == NULL)
410     return NULL;
411
412   _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE);
413   
414   *((dbus_uint32_t*)block) = requested_bytes;
415   *((dbus_uint32_t*)(block + 4)) = source;
416
417   i = GUARD_INFO_SIZE;
418   while (i < GUARD_START_OFFSET)
419     {
420       (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
421       
422       i += 4;
423     }
424
425   i = GUARD_START_OFFSET + requested_bytes;
426   while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
427     {
428       (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
429       
430       i += 4;
431     }
432   
433   check_guards (block + GUARD_START_OFFSET, FALSE);
434   
435   return block + GUARD_START_OFFSET;
436 }
437
438 #endif
439
440 /** @} */ /* End of internals docs */
441
442
443 /**
444  * @addtogroup DBusMemory
445  *
446  * @{
447  */
448
449 /**
450  * Allocates the given number of bytes, as with standard
451  * malloc(). Guaranteed to return #NULL if bytes is zero
452  * on all platforms. Returns #NULL if the allocation fails.
453  * The memory must be released with dbus_free().
454  *
455  * dbus_malloc() memory is NOT safe to free with regular free() from
456  * the C library. Free it with dbus_free() only.
457  *
458  * @param bytes number of bytes to allocate
459  * @return allocated memory, or #NULL if the allocation fails.
460  */
461 void*
462 dbus_malloc (size_t bytes)
463 {
464 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
465   _dbus_initialize_malloc_debug ();
466   
467   if (_dbus_decrement_fail_alloc_counter ())
468     {
469       _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes);
470       return NULL;
471     }
472 #endif
473
474   if (bytes == 0) /* some system mallocs handle this, some don't */
475     return NULL;
476 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
477   else if (fail_size != 0 && bytes > fail_size)
478     return NULL;
479   else if (guards)
480     {
481       void *block;
482
483       block = malloc (bytes + GUARD_EXTRA_SIZE);
484       if (block)
485         {
486           _dbus_atomic_inc (&n_blocks_outstanding);
487         }
488       else if (malloc_cannot_fail)
489         {
490           _dbus_warn ("out of memory: malloc (%ld + %ld)",
491               (long) bytes, (long) GUARD_EXTRA_SIZE);
492           _dbus_abort ();
493         }
494       
495       return set_guards (block, bytes, SOURCE_MALLOC);
496     }
497 #endif
498   else
499     {
500       void *mem;
501       mem = malloc (bytes);
502
503 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
504       if (mem)
505         {
506           _dbus_atomic_inc (&n_blocks_outstanding);
507         }
508       else if (malloc_cannot_fail)
509         {
510           _dbus_warn ("out of memory: malloc (%ld)", (long) bytes);
511           _dbus_abort ();
512         }
513 #endif
514
515       return mem;
516     }
517 }
518
519 /**
520  * Allocates the given number of bytes, as with standard malloc(), but
521  * all bytes are initialized to zero as with calloc(). Guaranteed to
522  * return #NULL if bytes is zero on all platforms. Returns #NULL if the
523  * allocation fails.  The memory must be released with dbus_free().
524  *
525  * dbus_malloc0() memory is NOT safe to free with regular free() from
526  * the C library. Free it with dbus_free() only.
527  *
528  * @param bytes number of bytes to allocate
529  * @return allocated memory, or #NULL if the allocation fails.
530  */
531 void*
532 dbus_malloc0 (size_t bytes)
533 {
534 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
535   _dbus_initialize_malloc_debug ();
536   
537   if (_dbus_decrement_fail_alloc_counter ())
538     {
539       _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes);
540       
541       return NULL;
542     }
543 #endif
544   
545   if (bytes == 0)
546     return NULL;
547 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
548   else if (fail_size != 0 && bytes > fail_size)
549     return NULL;
550   else if (guards)
551     {
552       void *block;
553
554       block = calloc (bytes + GUARD_EXTRA_SIZE, 1);
555
556       if (block)
557         {
558           _dbus_atomic_inc (&n_blocks_outstanding);
559         }
560       else if (malloc_cannot_fail)
561         {
562           _dbus_warn ("out of memory: calloc (%ld + %ld, 1)",
563               (long) bytes, (long) GUARD_EXTRA_SIZE);
564           _dbus_abort ();
565         }
566
567       return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
568     }
569 #endif
570   else
571     {
572       void *mem;
573       mem = calloc (bytes, 1);
574
575 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
576       if (mem)
577         {
578           _dbus_atomic_inc (&n_blocks_outstanding);
579         }
580       else if (malloc_cannot_fail)
581         {
582           _dbus_warn ("out of memory: calloc (%ld)", (long) bytes);
583           _dbus_abort ();
584         }
585 #endif
586
587       return mem;
588     }
589 }
590
591 /**
592  * Resizes a block of memory previously allocated by dbus_malloc() or
593  * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes
594  * is zero on all platforms. Returns #NULL if the resize fails.
595  * If the resize fails, the memory is not freed.
596  *
597  * @param memory block to be resized
598  * @param bytes new size of the memory block
599  * @return allocated memory, or #NULL if the resize fails.
600  */
601 void*
602 dbus_realloc (void  *memory,
603               size_t bytes)
604 {
605 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
606   _dbus_initialize_malloc_debug ();
607   
608   if (_dbus_decrement_fail_alloc_counter ())
609     {
610       _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes);
611       
612       return NULL;
613     }
614 #endif
615   
616   if (bytes == 0) /* guarantee this is safe */
617     {
618       dbus_free (memory);
619       return NULL;
620     }
621 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
622   else if (fail_size != 0 && bytes > fail_size)
623     return NULL;
624   else if (guards)
625     {
626       if (memory)
627         {
628           size_t old_bytes;
629           void *block;
630           
631           check_guards (memory, FALSE);
632           
633           block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
634                            bytes + GUARD_EXTRA_SIZE);
635
636           if (block == NULL)
637             {
638               if (malloc_cannot_fail)
639                 {
640                   _dbus_warn ("out of memory: realloc (%p, %ld + %ld)",
641                       memory, (long) bytes, (long) GUARD_EXTRA_SIZE);
642                   _dbus_abort ();
643                 }
644
645               return NULL;
646             }
647
648           old_bytes = *(dbus_uint32_t*)block;
649           if (bytes >= old_bytes)
650             /* old guards shouldn't have moved */
651             check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE);
652           
653           return set_guards (block, bytes, SOURCE_REALLOC);
654         }
655       else
656         {
657           void *block;
658           
659           block = malloc (bytes + GUARD_EXTRA_SIZE);
660
661           if (block)
662             {
663               _dbus_atomic_inc (&n_blocks_outstanding);
664             }
665           else if (malloc_cannot_fail)
666             {
667               _dbus_warn ("out of memory: malloc (%ld + %ld)",
668                   (long) bytes, (long) GUARD_EXTRA_SIZE);
669               _dbus_abort ();
670             }
671
672           return set_guards (block, bytes, SOURCE_REALLOC_NULL);   
673         }
674     }
675 #endif
676   else
677     {
678       void *mem;
679       mem = realloc (memory, bytes);
680
681 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
682       if (mem == NULL && malloc_cannot_fail)
683         {
684           _dbus_warn ("out of memory: malloc (%ld)", (long) bytes);
685           _dbus_abort ();
686         }
687
688       if (memory == NULL && mem != NULL)
689             _dbus_atomic_inc (&n_blocks_outstanding);
690 #endif
691       return mem;
692     }
693 }
694
695 /**
696  * Frees a block of memory previously allocated by dbus_malloc() or
697  * dbus_malloc0(). If passed #NULL, does nothing.
698  * 
699  * @param memory block to be freed
700  */
701 void
702 dbus_free (void  *memory)
703 {
704 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
705   if (guards)
706     {
707       check_guards (memory, TRUE);
708       if (memory)
709         {
710 #ifdef DBUS_DISABLE_ASSERT
711           _dbus_atomic_dec (&n_blocks_outstanding);
712 #else
713           dbus_int32_t old_value;
714
715           old_value = _dbus_atomic_dec (&n_blocks_outstanding);
716           _dbus_assert (old_value >= 1);
717 #endif
718
719           free (((unsigned char*)memory) - GUARD_START_OFFSET);
720         }
721       
722       return;
723     }
724 #endif
725     
726   if (memory) /* we guarantee it's safe to free (NULL) */
727     {
728 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
729 #ifdef DBUS_DISABLE_ASSERT
730       _dbus_atomic_dec (&n_blocks_outstanding);
731 #else
732       dbus_int32_t old_value;
733
734       old_value = _dbus_atomic_dec (&n_blocks_outstanding);
735       _dbus_assert (old_value >= 1);
736 #endif
737 #endif
738
739       free (memory);
740     }
741 }
742
743 /**
744  * Frees a #NULL-terminated array of strings.
745  * If passed #NULL, does nothing.
746  *
747  * @param str_array the array to be freed
748  */
749 void
750 dbus_free_string_array (char **str_array)
751 {
752   if (str_array)
753     {
754       int i;
755
756       i = 0;
757       while (str_array[i])
758         {
759           dbus_free (str_array[i]);
760           i++;
761         }
762
763       dbus_free (str_array);
764     }
765 }
766
767 /** @} */ /* End of public API docs block */
768
769
770 /**
771  * @addtogroup DBusMemoryInternals
772  *
773  * @{
774  */
775
776 /**
777  * _dbus_current_generation is used to track each
778  * time that dbus_shutdown() is called, so we can
779  * reinit things after it's been called. It is simply
780  * incremented each time we shut down.
781  */
782 int _dbus_current_generation = 1;
783
784 /**
785  * Represents a function to be called on shutdown.
786  */
787 typedef struct ShutdownClosure ShutdownClosure;
788
789 /**
790  * This struct represents a function to be called on shutdown.
791  */
792 struct ShutdownClosure
793 {
794   ShutdownClosure *next;     /**< Next ShutdownClosure */
795   DBusShutdownFunction func; /**< Function to call */
796   void *data;                /**< Data for function */
797 };
798
799 /* Protected by _DBUS_LOCK (shutdown_funcs) */
800 static ShutdownClosure *registered_globals = NULL;
801
802 /**
803  * Register a cleanup function to be called exactly once
804  * the next time dbus_shutdown() is called.
805  *
806  * @param func the function
807  * @param data data to pass to the function
808  * @returns #FALSE on not enough memory
809  */
810 dbus_bool_t
811 _dbus_register_shutdown_func (DBusShutdownFunction  func,
812                               void                 *data)
813 {
814   dbus_bool_t ok;
815
816   if (!_DBUS_LOCK (shutdown_funcs))
817     return FALSE;
818
819   ok = _dbus_register_shutdown_func_unlocked (func, data);
820   _DBUS_UNLOCK (shutdown_funcs);
821   return ok;
822 }
823
824 dbus_bool_t
825 _dbus_register_shutdown_func_unlocked (DBusShutdownFunction  func,
826                                        void                 *data)
827 {
828   ShutdownClosure *c;
829
830   c = dbus_new (ShutdownClosure, 1);
831
832   if (c == NULL)
833     return FALSE;
834
835   c->func = func;
836   c->data = data;
837
838   c->next = registered_globals;
839   registered_globals = c;
840
841   return TRUE;
842 }
843
844 /** @} */ /* End of private API docs block */
845
846
847 /**
848  * @addtogroup DBusMemory
849  *
850  * @{
851  */
852
853 /**
854  * Frees all memory allocated internally by libdbus and
855  * reverses the effects of dbus_threads_init(). libdbus keeps internal
856  * global variables, for example caches and thread locks, and it
857  * can be useful to free these internal data structures.
858  *
859  * dbus_shutdown() does NOT free memory that was returned
860  * to the application. It only frees libdbus-internal
861  * data structures.
862  *
863  * You MUST free all memory and release all reference counts
864  * returned to you by libdbus prior to calling dbus_shutdown().
865  *
866  * If a shared connection is open, calling dbus_shutdown() will
867  * drain its queue of messages and disconnect it. In particular,
868  * this will result in processing of the special Disconnected
869  * signal, which may result in a call to _exit(), unless you
870  * have used dbus_connection_set_exit_on_disconnect() to disable
871  * that behaviour.
872  *
873  * You can't continue to use any D-Bus objects, such as connections,
874  * that were allocated prior to dbus_shutdown(). You can, however,
875  * start over; call dbus_threads_init() again, create new connections,
876  * and so forth.
877  *
878  * WARNING: dbus_shutdown() is NOT thread safe, it must be called
879  * while NO other threads are using D-Bus. (Remember, you have to free
880  * all D-Bus objects and memory before you call dbus_shutdown(), so no
881  * thread can be using libdbus.)
882  *
883  * The purpose of dbus_shutdown() is to allow applications to get
884  * clean output from memory leak checkers. dbus_shutdown() may also be
885  * useful if you want to dlopen() libdbus instead of linking to it,
886  * and want to be able to unload the library again.
887  *
888  * There is absolutely no requirement to call dbus_shutdown() - in fact,
889  * most applications won't bother and should not feel guilty.
890  * 
891  * You have to know that nobody is using libdbus in your application's
892  * process before you can call dbus_shutdown(). One implication of this
893  * is that calling dbus_shutdown() from a library is almost certainly
894  * wrong, since you don't know what the rest of the app is up to.
895  * 
896  */
897 void
898 dbus_shutdown (void)
899 {
900   while (registered_globals != NULL)
901     {
902       ShutdownClosure *c;
903
904       c = registered_globals;
905       registered_globals = c->next;
906       
907       (* c->func) (c->data);
908       
909       dbus_free (c);
910     }
911
912   /* We wrap this in the thread-initialization lock because
913    * dbus_threads_init() uses the current generation to tell whether
914    * we're initialized, so we need to make sure that un-initializing
915    * propagates into all threads. */
916   _dbus_threads_lock_platform_specific ();
917   _dbus_current_generation += 1;
918   _dbus_threads_unlock_platform_specific ();
919 }
920
921 /** @} */ /** End of public API docs block */
922
923 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
924 #include "dbus-test.h"
925
926 /**
927  * @ingroup DBusMemoryInternals
928  * Unit test for DBusMemory
929  * @returns #TRUE on success.
930  */
931 dbus_bool_t
932 _dbus_memory_test (void)
933 {
934   dbus_bool_t old_guards;
935   void *p;
936   size_t size;
937
938   old_guards = guards;
939   guards = TRUE;
940   p = dbus_malloc (4);
941   if (p == NULL)
942     _dbus_assert_not_reached ("no memory");
943   for (size = 4; size < 256; size += 4)
944     {
945       p = dbus_realloc (p, size);
946       if (p == NULL)
947         _dbus_assert_not_reached ("no memory");
948     }
949   for (size = 256; size != 0; size -= 4)
950     {
951       p = dbus_realloc (p, size);
952       if (p == NULL)
953         _dbus_assert_not_reached ("no memory");
954     }
955   dbus_free (p);
956   guards = old_guards;
957   return TRUE;
958 }
959
960 #endif