2003-02-14 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Fri, 14 Feb 2003 04:54:55 +0000 (04:54 +0000)
committerHavoc Pennington <hp@redhat.com>
Fri, 14 Feb 2003 04:54:55 +0000 (04:54 +0000)
* dbus/dbus-mempool.c: fail if the debug functions so indicate

* dbus/dbus-memory.c: fail if the debug functions indicate we
should

* dbus/dbus-internals.c (_dbus_set_fail_alloc_counter)
(_dbus_decrement_fail_alloc_counter): debug functions to
simulate memory allocation failures

ChangeLog
dbus/dbus-internals.c
dbus/dbus-internals.h
dbus/dbus-memory.c
dbus/dbus-mempool.c
dbus/dbus-message.c

index b3516d5..ff3f295 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2003-02-14  Havoc Pennington  <hp@pobox.com>
 
+       * dbus/dbus-mempool.c: fail if the debug functions so indicate
+
+       * dbus/dbus-memory.c: fail if the debug functions indicate we
+       should
+
+       * dbus/dbus-internals.c (_dbus_set_fail_alloc_counter)
+       (_dbus_decrement_fail_alloc_counter): debug functions to 
+       simulate memory allocation failures
+
+2003-02-14  Havoc Pennington  <hp@pobox.com>
+
        * dbus/dbus-errors.h (struct DBusError): add a word of padding 
        to DBusError
 
index 78a1b68..d51f5a9 100644 (file)
@@ -391,4 +391,56 @@ _dbus_type_to_string (int type)
     }
 }
 
+#ifdef DBUS_BUILD_TESTS
+static int fail_alloc_counter = _DBUS_INT_MAX;
+/**
+ * Sets the number of allocations until we simulate a failed
+ * allocation. If set to 0, the next allocation to run
+ * fails; if set to 1, one succeeds then the next fails; etc.
+ * Set to _DBUS_INT_MAX to not fail anything. 
+ *
+ * @param until_next_fail number of successful allocs before one fails
+ */
+void
+_dbus_set_fail_alloc_counter (int until_next_fail)
+{
+  fail_alloc_counter = until_next_fail;
+}
+
+/**
+ * Gets the number of successful allocs until we'll simulate
+ * a failed alloc.
+ *
+ * @returns current counter value
+ */
+int
+_dbus_get_fail_alloc_counter (void)
+{
+  return fail_alloc_counter;
+}
+
+/**
+ * Called when about to alloc some memory; if
+ * it returns #TRUE, then the allocation should
+ * fail. If it returns #FALSE, then the allocation
+ * should not fail.
+ *
+ * @returns #TRUE if this alloc should fail
+ */
+dbus_bool_t
+_dbus_decrement_fail_alloc_counter (void)
+{
+  if (fail_alloc_counter <= 0)
+    {
+      fail_alloc_counter = _DBUS_INT_MAX;
+      return TRUE;
+    }
+  else
+    {
+      fail_alloc_counter -= 1;
+      return FALSE;
+    }
+}
+#endif /* DBUS_BUILD_TESTS */
+
 /** @} */
index f0baf46..29dd41c 100644 (file)
@@ -142,6 +142,17 @@ void _dbus_verbose_bytes_of_string (const DBusString    *str,
 
 const char* _dbus_type_to_string (int type);
 
+#ifdef DBUS_BUILD_TESTS
+/* Memory debugging */
+void        _dbus_set_fail_alloc_counter       (int  until_next_fail);
+int         _dbus_get_fail_alloc_counter       (void);
+dbus_bool_t _dbus_decrement_fail_alloc_counter (void);
+#else
+#define _dbus_set_fail_alloc_counter(n)
+#define _dbus_get_fail_alloc_counter _DBUS_INT_MAX
+#define _dbus_decrement_fail_alloc_counter FALSE
+#endif /* !DBUS_BUILD_TESTS */
+
 DBUS_END_DECLS;
 
 #endif /* DBUS_INTERNALS_H */
index 52a563e..357e8be 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-memory.c  D-BUS memory handling
  *
- * Copyright (C) 2002  Red Hat Inc.
+ * Copyright (C) 2002, 2003  Red Hat Inc.
  *
  * Licensed under the Academic Free License version 1.2
  * 
@@ -22,6 +22,7 @@
  */
 
 #include "dbus-memory.h"
+#include "dbus-internals.h"
 #include <stdlib.h>
 
 /**
@@ -82,6 +83,9 @@
 void*
 dbus_malloc (size_t bytes)
 {
+  if (_dbus_decrement_fail_alloc_counter ())
+    return NULL;
+  
   if (bytes == 0) /* some system mallocs handle this, some don't */
     return NULL;
   else
@@ -100,6 +104,9 @@ dbus_malloc (size_t bytes)
 void*
 dbus_malloc0 (size_t bytes)
 {
+  if (_dbus_decrement_fail_alloc_counter ())
+    return NULL;
+
   if (bytes == 0)
     return NULL;
   else
@@ -120,6 +127,9 @@ void*
 dbus_realloc (void  *memory,
               size_t bytes)
 {
+  if (_dbus_decrement_fail_alloc_counter ())
+    return NULL;
+  
   if (bytes == 0) /* guarantee this is safe */
     {
       dbus_free (memory);
index 05e3749..3b233dd 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-mempool.h Memory pools
  * 
- * Copyright (C) 2002  Red Hat, Inc.
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
  *
  * Licensed under the Academic Free License version 1.2
  * 
@@ -195,6 +195,9 @@ _dbus_mem_pool_free (DBusMemPool *pool)
 void*
 _dbus_mem_pool_alloc (DBusMemPool *pool)
 {
+  if (_dbus_decrement_fail_alloc_counter ())
+    return NULL;
+  
   if (pool->free_elements)
     {
       DBusFreedElement *element = pool->free_elements;
@@ -216,7 +219,10 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
           /* Need a new block */
           DBusMemBlock *block;
           int alloc_size;
-
+#ifdef DBUS_BUILD_TESTS
+          int saved_counter;
+#endif
+          
           if (pool->block_size <= _DBUS_INT_MAX / 4) /* avoid overflow */
             {
               /* use a larger block size for our next block */
@@ -226,12 +232,27 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
             }
 
           alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->block_size;
+
+#ifdef DBUS_BUILD_TESTS
+          /* We save/restore the counter, so that memory pools won't
+           * cause a given function to have different number of
+           * allocations on different invocations. i.e.  when testing
+           * we want consistent alloc patterns. So we skip our
+           * malloc here for purposes of failed alloc simulation.
+           */
+          saved_counter = _dbus_get_fail_alloc_counter ();
+          _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+#endif
           
           if (pool->zero_elements)
             block = dbus_malloc0 (alloc_size);
           else
             block = dbus_malloc (alloc_size);
 
+#ifdef DBUS_BUILD_TESTS
+          _dbus_set_fail_alloc_counter (saved_counter);
+#endif
+          
           if (block == NULL)
             return NULL;
 
index 4287bd9..4ea2a63 100644 (file)
@@ -2006,6 +2006,12 @@ decode_header_data (const DBusString   *data,
  * in. This function must always be called, even if no bytes were
  * successfully read.
  *
+ * @todo if we run out of memory in here, we offer no way for calling
+ * code to handle it, i.e. they can't re-run the message parsing
+ * attempt. Perhaps much of this code could be moved to pop_message()?
+ * But then that may need to distinguish NULL return for no messages
+ * from NULL return for errors.
+ *
  * @param loader the loader.
  * @param buffer the buffer.
  * @param bytes_read number of bytes that were read into the buffer.