2003-06-29 Miloslav Trmac <mitr@volny.cz>
[platform/upstream/dbus.git] / dbus / dbus-memory.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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 1.2
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-memory.h"
25 #include "dbus-internals.h"
26 #include "dbus-sysdeps.h"
27 #include "dbus-list.h"
28 #include <stdlib.h>
29
30 /**
31  * @defgroup DBusMemory Memory Allocation
32  * @ingroup  DBus
33  * @brief dbus_malloc(), dbus_free(), etc.
34  *
35  * Functions and macros related to allocating and releasing
36  * blocks of memory.
37  *
38  */
39
40 /**
41  * @defgroup DBusMemoryInternals Memory allocation implementation details
42  * @ingroup  DBusInternals
43  * @brief internals of dbus_malloc() etc.
44  *
45  * Implementation details related to allocating and releasing blocks
46  * of memory.
47  */
48
49 /**
50  * @addtogroup DBusMemory
51  *
52  * @{
53  */
54
55 /**
56  * @def dbus_new
57  *
58  * Safe macro for using dbus_malloc(). Accepts the type
59  * to allocate and the number of type instances to
60  * allocate as arguments, and returns a memory block
61  * cast to the desired type, instead of as a void*.
62  *
63  * @param type type name to allocate
64  * @param count number of instances in the allocated array
65  * @returns the new memory block or #NULL on failure
66  */
67
68 /**
69  * @def dbus_new0
70  *
71  * Safe macro for using dbus_malloc0(). Accepts the type
72  * to allocate and the number of type instances to
73  * allocate as arguments, and returns a memory block
74  * cast to the desired type, instead of as a void*.
75  * The allocated array is initialized to all-bits-zero.
76  *
77  * @param type type name to allocate
78  * @param count number of instances in the allocated array
79  * @returns the new memory block or #NULL on failure
80  */
81
82 /**
83  * @typedef DBusFreeFunction
84  *
85  * The type of a function which frees a block of memory.
86  *
87  * @param memory the memory to free
88  */
89
90 /** @} */ /* end of public API docs */
91
92 /**
93  * @addtogroup DBusMemoryInternals
94  *
95  * @{
96  */
97
98 #ifdef DBUS_BUILD_TESTS
99 static dbus_bool_t debug_initialized = FALSE;
100 static int fail_nth = -1;
101 static size_t fail_size = 0;
102 static int fail_alloc_counter = _DBUS_INT_MAX;
103 static int n_failures_per_failure = 1;
104 static int n_failures_this_failure = 0;
105 static dbus_bool_t guards = FALSE;
106 static dbus_bool_t disable_mem_pools = FALSE;
107 static dbus_bool_t backtrace_on_fail_alloc = FALSE;
108 static int n_blocks_outstanding = 0;
109
110 /** value stored in guard padding for debugging buffer overrun */
111 #define GUARD_VALUE 0xdeadbeef
112 /** size of the information about the block stored in guard mode */
113 #define GUARD_INFO_SIZE 8
114 /** size of the GUARD_VALUE-filled padding after the header info  */
115 #define GUARD_START_PAD 16
116 /** size of the GUARD_VALUE-filled padding at the end of the block */
117 #define GUARD_END_PAD 16
118 /** size of stuff at start of block */
119 #define GUARD_START_OFFSET (GUARD_START_PAD + GUARD_INFO_SIZE)
120 /** total extra size over the requested allocation for guard stuff */
121 #define GUARD_EXTRA_SIZE (GUARD_START_OFFSET + GUARD_END_PAD)
122
123 static void
124 _dbus_initialize_malloc_debug (void)
125 {
126   if (!debug_initialized)
127     {
128       debug_initialized = TRUE;
129       
130       if (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH") != NULL)
131         {
132           fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH"));
133           fail_alloc_counter = fail_nth;
134           _dbus_verbose ("Will fail malloc every %d times\n", fail_nth);
135         }
136       
137       if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL)
138         {
139           fail_size = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN"));
140           _dbus_verbose ("Will fail mallocs over %d bytes\n",
141                          fail_size);
142         }
143
144       if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL)
145         {
146           guards = TRUE;
147           _dbus_verbose ("Will use malloc guards\n");
148         }
149
150       if (_dbus_getenv ("DBUS_DISABLE_MEM_POOLS") != NULL)
151         {
152           disable_mem_pools = TRUE;
153           _dbus_verbose ("Will disable memory pools\n");
154         }
155
156       if (_dbus_getenv ("DBUS_MALLOC_BACKTRACES") != NULL)
157         {
158           backtrace_on_fail_alloc = TRUE;
159           _dbus_verbose ("Will backtrace on failing a malloc\n");
160         }
161     }
162 }
163
164 /**
165  * Whether to turn off mem pools, useful for leak checking.
166  *
167  * @returns #TRUE if mempools should not be used.
168  */
169 dbus_bool_t
170 _dbus_disable_mem_pools (void)
171 {
172   _dbus_initialize_malloc_debug ();
173   return disable_mem_pools;
174 }
175
176 /**
177  * Sets the number of allocations until we simulate a failed
178  * allocation. If set to 0, the next allocation to run
179  * fails; if set to 1, one succeeds then the next fails; etc.
180  * Set to _DBUS_INT_MAX to not fail anything. 
181  *
182  * @param until_next_fail number of successful allocs before one fails
183  */
184 void
185 _dbus_set_fail_alloc_counter (int until_next_fail)
186 {
187   _dbus_initialize_malloc_debug ();
188
189   fail_alloc_counter = until_next_fail;
190
191 #if 0
192   _dbus_verbose ("Set fail alloc counter = %d\n", fail_alloc_counter);
193 #endif
194 }
195
196 /**
197  * Gets the number of successful allocs until we'll simulate
198  * a failed alloc.
199  *
200  * @returns current counter value
201  */
202 int
203 _dbus_get_fail_alloc_counter (void)
204 {
205   _dbus_initialize_malloc_debug ();
206
207   return fail_alloc_counter;
208 }
209
210 /**
211  * Sets how many mallocs to fail when the fail alloc counter reaches
212  * 0.
213  *
214  * @param failures_per_failure number to fail
215  */
216 void
217 _dbus_set_fail_alloc_failures (int failures_per_failure)
218 {
219   n_failures_per_failure = failures_per_failure;
220 }
221
222 /**
223  * Gets the number of failures we'll have when the fail malloc
224  * counter reaches 0.
225  *
226  * @returns number of failures planned
227  */
228 int
229 _dbus_get_fail_alloc_failures (void)
230 {
231   return n_failures_per_failure;
232 }
233
234 /**
235  * Called when about to alloc some memory; if
236  * it returns #TRUE, then the allocation should
237  * fail. If it returns #FALSE, then the allocation
238  * should not fail.
239  *
240  * @returns #TRUE if this alloc should fail
241  */
242 dbus_bool_t
243 _dbus_decrement_fail_alloc_counter (void)
244 {
245   _dbus_initialize_malloc_debug ();
246   
247   if (fail_alloc_counter <= 0)
248     {
249       if (backtrace_on_fail_alloc)
250         _dbus_print_backtrace ();
251
252       _dbus_verbose ("failure %d\n", n_failures_this_failure);
253       
254       n_failures_this_failure += 1;
255       if (n_failures_this_failure >= n_failures_per_failure)
256         {
257           if (fail_nth >= 0)
258             fail_alloc_counter = fail_nth;
259           else
260             fail_alloc_counter = _DBUS_INT_MAX;
261
262           n_failures_this_failure = 0;
263
264           _dbus_verbose ("reset fail alloc counter to %d\n", fail_alloc_counter);
265         }
266       
267       return TRUE;
268     }
269   else
270     {
271       fail_alloc_counter -= 1;
272       return FALSE;
273     }
274 }
275
276 /**
277  * Get the number of outstanding malloc()'d blocks.
278  *
279  * @returns number of blocks
280  */
281 int
282 _dbus_get_malloc_blocks_outstanding (void)
283 {
284   return n_blocks_outstanding;
285 }
286
287 /**
288  * Where the block came from.
289  */
290 typedef enum
291 {
292   SOURCE_UNKNOWN,
293   SOURCE_MALLOC,
294   SOURCE_REALLOC,
295   SOURCE_MALLOC_ZERO,
296   SOURCE_REALLOC_NULL
297 } BlockSource;
298
299 static const char*
300 source_string (BlockSource source)
301 {
302   switch (source)
303     {
304     case SOURCE_UNKNOWN:
305       return "unknown";
306     case SOURCE_MALLOC:
307       return "malloc";
308     case SOURCE_REALLOC:
309       return "realloc";
310     case SOURCE_MALLOC_ZERO:
311       return "malloc0";
312     case SOURCE_REALLOC_NULL:
313       return "realloc(NULL)";
314     }
315   _dbus_assert_not_reached ("Invalid malloc block source ID");
316   return "invalid!";
317 }
318
319 static void
320 check_guards (void *free_block)
321 {
322   if (free_block != NULL)
323     {
324       unsigned char *block = ((unsigned char*)free_block) - GUARD_START_OFFSET;
325       size_t requested_bytes = *(dbus_uint32_t*)block;
326       BlockSource source = *(dbus_uint32_t*)(block + 4);
327       unsigned int i;
328       dbus_bool_t failed;
329
330       failed = FALSE;
331
332 #if 0
333       _dbus_verbose ("Checking %d bytes request from source %s\n",
334                      requested_bytes, source_string (source));
335 #endif
336       
337       i = GUARD_INFO_SIZE;
338       while (i < GUARD_START_OFFSET)
339         {
340           dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
341           if (value != GUARD_VALUE)
342             {
343               _dbus_warn ("Block of %u bytes from %s had start guard value 0x%x at %d expected 0x%x\n",
344                           requested_bytes, source_string (source),
345                           value, i, GUARD_VALUE);
346               failed = TRUE;
347             }
348           
349           i += 4;
350         }
351
352       i = GUARD_START_OFFSET + requested_bytes;
353       while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
354         {
355           dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
356           if (value != GUARD_VALUE)
357             {
358               _dbus_warn ("Block of %u bytes from %s had end guard value 0x%x at %d expected 0x%x\n",
359                           requested_bytes, source_string (source),
360                           value, i, GUARD_VALUE);
361               failed = TRUE;
362             }
363           
364           i += 4;
365         }
366
367       if (failed)
368         _dbus_assert_not_reached ("guard value corruption");
369     }
370 }
371
372 static void*
373 set_guards (void       *real_block,
374             size_t      requested_bytes,
375             BlockSource source)
376 {
377   unsigned char *block = real_block;
378   unsigned int i;
379   
380   if (block == NULL)
381     return NULL;
382
383   _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE);
384   
385   *((dbus_uint32_t*)block) = requested_bytes;
386   *((dbus_uint32_t*)(block + 4)) = source;
387
388   i = GUARD_INFO_SIZE;
389   while (i < GUARD_START_OFFSET)
390     {
391       (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
392       
393       i += 4;
394     }
395
396   i = GUARD_START_OFFSET + requested_bytes;
397   while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
398     {
399       (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
400       
401       i += 4;
402     }
403   
404   check_guards (block + GUARD_START_OFFSET);
405   
406   return block + GUARD_START_OFFSET;
407 }
408
409 #endif
410
411 /** @} */ /* End of internals docs */
412
413
414 /**
415  * @addtogroup DBusMemory
416  *
417  * @{
418  */
419
420 /**
421  * Allocates the given number of bytes, as with standard
422  * malloc(). Guaranteed to return #NULL if bytes is zero
423  * on all platforms. Returns #NULL if the allocation fails.
424  * The memory must be released with dbus_free().
425  *
426  * @param bytes number of bytes to allocate
427  * @return allocated memory, or #NULL if the allocation fails.
428  */
429 void*
430 dbus_malloc (size_t bytes)
431 {
432 #ifdef DBUS_BUILD_TESTS
433   _dbus_initialize_malloc_debug ();
434   
435   if (_dbus_decrement_fail_alloc_counter ())
436     {
437       _dbus_verbose (" FAILING malloc of %d bytes\n", bytes);
438       
439       return NULL;
440     }
441 #endif
442   
443   if (bytes == 0) /* some system mallocs handle this, some don't */
444     return NULL;
445 #ifdef DBUS_BUILD_TESTS
446   else if (fail_size != 0 && bytes > fail_size)
447     return NULL;
448   else if (guards)
449     {
450       void *block;
451
452       block = malloc (bytes + GUARD_EXTRA_SIZE);
453       if (block)
454         n_blocks_outstanding += 1;
455       
456       return set_guards (block, bytes, SOURCE_MALLOC);
457     }
458 #endif
459   else
460     {
461       void *mem;
462       mem = malloc (bytes);
463 #ifdef DBUS_BUILD_TESTS
464       if (mem)
465         n_blocks_outstanding += 1;
466 #endif
467       return mem;
468     }
469 }
470
471 /**
472  * Allocates the given number of bytes, as with standard malloc(), but
473  * all bytes are initialized to zero as with calloc(). Guaranteed to
474  * return #NULL if bytes is zero on all platforms. Returns #NULL if the
475  * allocation fails.  The memory must be released with dbus_free().
476  *
477  * @param bytes number of bytes to allocate
478  * @return allocated memory, or #NULL if the allocation fails.
479  */
480 void*
481 dbus_malloc0 (size_t bytes)
482 {
483 #ifdef DBUS_BUILD_TESTS
484   _dbus_initialize_malloc_debug ();
485   
486   if (_dbus_decrement_fail_alloc_counter ())
487     {
488       _dbus_verbose (" FAILING malloc0 of %d bytes\n", bytes);
489       
490       return NULL;
491     }
492 #endif
493
494   if (bytes == 0)
495     return NULL;
496 #ifdef DBUS_BUILD_TESTS
497   else if (fail_size != 0 && bytes > fail_size)
498     return NULL;
499   else if (guards)
500     {
501       void *block;
502
503       block = calloc (bytes + GUARD_EXTRA_SIZE, 1);
504       if (block)
505         n_blocks_outstanding += 1;
506       return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
507     }
508 #endif
509   else
510     {
511       void *mem;
512       mem = calloc (bytes, 1);
513 #ifdef DBUS_BUILD_TESTS
514       if (mem)
515         n_blocks_outstanding += 1;
516 #endif
517       return mem;
518     }
519 }
520
521 /**
522  * Resizes a block of memory previously allocated by dbus_malloc() or
523  * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes
524  * is zero on all platforms. Returns #NULL if the resize fails.
525  * If the resize fails, the memory is not freed.
526  *
527  * @param memory block to be resized
528  * @param bytes new size of the memory block
529  * @return allocated memory, or #NULL if the resize fails.
530  */
531 void*
532 dbus_realloc (void  *memory,
533               size_t bytes)
534 {
535 #ifdef DBUS_BUILD_TESTS
536   _dbus_initialize_malloc_debug ();
537   
538   if (_dbus_decrement_fail_alloc_counter ())
539     {
540       _dbus_verbose (" FAILING realloc of %d bytes\n", bytes);
541       
542       return NULL;
543     }
544 #endif
545   
546   if (bytes == 0) /* guarantee this is safe */
547     {
548       dbus_free (memory);
549       return NULL;
550     }
551 #ifdef DBUS_BUILD_TESTS
552   else if (fail_size != 0 && bytes > fail_size)
553     return NULL;
554   else if (guards)
555     {
556       if (memory)
557         {
558           size_t old_bytes;
559           void *block;
560           
561           check_guards (memory);
562           
563           block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
564                            bytes + GUARD_EXTRA_SIZE);
565
566           old_bytes = *(dbus_uint32_t*)block;
567           if (block && bytes >= old_bytes)
568             /* old guards shouldn't have moved */
569             check_guards (((unsigned char*)block) + GUARD_START_OFFSET);
570           
571           return set_guards (block, bytes, SOURCE_REALLOC);
572         }
573       else
574         {
575           void *block;
576           
577           block = malloc (bytes + GUARD_EXTRA_SIZE);
578
579           if (block)
580             n_blocks_outstanding += 1;
581           
582           return set_guards (block, bytes, SOURCE_REALLOC_NULL);   
583         }
584     }
585 #endif
586   else
587     {
588       void *mem;
589       mem = realloc (memory, bytes);
590 #ifdef DBUS_BUILD_TESTS
591       if (memory == NULL && mem != NULL)
592         n_blocks_outstanding += 1;
593 #endif
594       return mem;
595     }
596 }
597
598 /**
599  * Frees a block of memory previously allocated by dbus_malloc() or
600  * dbus_malloc0(). If passed #NULL, does nothing.
601  * 
602  * @param memory block to be freed
603  */
604 void
605 dbus_free (void  *memory)
606 {
607 #ifdef DBUS_BUILD_TESTS
608   if (guards)
609     {
610       check_guards (memory);
611       if (memory)
612         {
613           n_blocks_outstanding -= 1;
614           
615           _dbus_assert (n_blocks_outstanding >= 0);
616           
617           free (((unsigned char*)memory) - GUARD_START_OFFSET);
618         }
619       
620       return;
621     }
622 #endif
623     
624   if (memory) /* we guarantee it's safe to free (NULL) */
625     {
626 #ifdef DBUS_BUILD_TESTS
627       n_blocks_outstanding -= 1;
628       
629       _dbus_assert (n_blocks_outstanding >= 0);
630 #endif
631
632       free (memory);
633     }
634 }
635
636 /**
637  * Frees a #NULL-terminated array of strings.
638  * If passed #NULL, does nothing.
639  *
640  * @param str_array the array to be freed
641  */
642 void
643 dbus_free_string_array (char **str_array)
644 {
645   if (str_array)
646     {
647       int i;
648
649       i = 0;
650       while (str_array[i])
651         {
652           dbus_free (str_array[i]);
653           i++;
654         }
655
656       dbus_free (str_array);
657     }
658 }
659
660 /** @} */ /* End of public API docs block */
661
662
663 /**
664  * @addtogroup DBusMemoryInternals
665  *
666  * @{
667  */
668
669 /**
670  * _dbus_current_generation is used to track each
671  * time that dbus_shutdown() is called, so we can
672  * reinit things after it's been called. It is simply
673  * incremented each time we shut down.
674  */
675 int _dbus_current_generation = 1;
676
677 /**
678  * Represents a function to be called on shutdown.
679  */
680 typedef struct ShutdownClosure ShutdownClosure;
681
682 /**
683  * This struct represents a function to be called on shutdown.
684  */
685 struct ShutdownClosure
686 {
687   ShutdownClosure *next;     /**< Next ShutdownClosure */
688   DBusShutdownFunction func; /**< Function to call */
689   void *data;                /**< Data for function */
690 };
691
692 _DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
693 static ShutdownClosure *registered_globals = NULL;
694
695 /**
696  * Register a cleanup function to be called exactly once
697  * the next time dbus_shutdown() is called.
698  *
699  * @param func the function
700  * @param data data to pass to the function
701  * @returns #FALSE on not enough memory
702  */
703 dbus_bool_t
704 _dbus_register_shutdown_func (DBusShutdownFunction  func,
705                               void                 *data)
706 {
707   ShutdownClosure *c;
708
709   c = dbus_new (ShutdownClosure, 1);
710
711   if (c == NULL)
712     return FALSE;
713
714   c->func = func;
715   c->data = data;
716
717   _DBUS_LOCK (shutdown_funcs);
718   
719   c->next = registered_globals;
720   registered_globals = c;
721
722   _DBUS_UNLOCK (shutdown_funcs);
723   
724   return TRUE;
725 }
726
727 /** @} */ /* End of private API docs block */
728
729
730 /**
731  * @addtogroup DBusMemory
732  *
733  * @{
734  */
735
736 /**
737  * The D-BUS library keeps some internal global variables, for example
738  * to cache the username of the current process.  This function is
739  * used to free these global variables.  It is really useful only for
740  * leak-checking cleanliness and the like. WARNING: this function is
741  * NOT thread safe, it must be called while NO other threads are using
742  * D-BUS. You cannot continue using D-BUS after calling this function,
743  * as it does things like free global mutexes created by
744  * dbus_threads_init(). To use a D-BUS function after calling
745  * dbus_shutdown(), you have to start over from scratch, e.g. calling
746  * dbus_threads_init() again.
747  */
748 void
749 dbus_shutdown (void)
750 {
751   while (registered_globals != NULL)
752     {
753       ShutdownClosure *c;
754
755       c = registered_globals;
756       registered_globals = c->next;
757       
758       (* c->func) (c->data);
759       
760       dbus_free (c);
761     }
762
763   _dbus_current_generation += 1;
764 }
765
766 /** @} */ /** End of public API docs block */
767
768 #ifdef DBUS_BUILD_TESTS
769 #include "dbus-test.h"
770
771 /**
772  * @ingroup DBusMemoryInternals
773  * Unit test for DBusMemory
774  * @returns #TRUE on success.
775  */
776 dbus_bool_t
777 _dbus_memory_test (void)
778 {
779   dbus_bool_t old_guards;
780   void *p;
781   size_t size;
782
783   old_guards = guards;
784   guards = TRUE;
785   p = dbus_malloc (4);
786   if (p == NULL)
787     _dbus_assert_not_reached ("no memory");
788   for (size = 4; size < 256; size += 4)
789     {
790       p = dbus_realloc (p, size);
791       if (p == NULL)
792         _dbus_assert_not_reached ("no memory");
793     }
794   for (size = 256; size != 0; size -= 4)
795     {
796       p = dbus_realloc (p, size);
797       if (p == NULL)
798         _dbus_assert_not_reached ("no memory");
799     }
800   dbus_free (p);
801   guards = old_guards;
802   return TRUE;
803 }
804
805 #endif