mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-17 22:58:07 +02:00
2003-03-28 Havoc Pennington <hp@pobox.com>
* bus/test.c (bus_test_flush_bus): remove the sleep from here, I think it may have just been superstition. Not sure. * dbus/dbus-string.c (_dbus_string_base64_decode): catch some OOM failures that were not being handled. * dbus/dbus-auth.c (process_auth): fix a memleak in OOM handling * dbus/dbus-memory.c: add ability to set number of mallocs in a row that will fail on out-of-memory. * dbus/dbus-internals.c (_dbus_test_oom_handling): convenience function for testing out-of-memory handling. * bus/config-loader-expat.c (memsuite): don't wrap the dbus allocation functions, they do map exactly to the expat ones.
This commit is contained in:
parent
574c258bc9
commit
bf99381351
13 changed files with 235 additions and 121 deletions
19
ChangeLog
19
ChangeLog
|
|
@ -1,3 +1,22 @@
|
|||
2003-03-28 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* bus/test.c (bus_test_flush_bus): remove the sleep from here,
|
||||
I think it may have just been superstition. Not sure.
|
||||
|
||||
* dbus/dbus-string.c (_dbus_string_base64_decode): catch some OOM
|
||||
failures that were not being handled.
|
||||
|
||||
* dbus/dbus-auth.c (process_auth): fix a memleak in OOM handling
|
||||
|
||||
* dbus/dbus-memory.c: add ability to set number of mallocs in a
|
||||
row that will fail on out-of-memory.
|
||||
|
||||
* dbus/dbus-internals.c (_dbus_test_oom_handling): convenience
|
||||
function for testing out-of-memory handling.
|
||||
|
||||
* bus/config-loader-expat.c (memsuite): don't wrap the dbus
|
||||
allocation functions, they do map exactly to the expat ones.
|
||||
|
||||
2003-03-27 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* bus/config-loader-libxml.c (bus_config_load): add another error
|
||||
|
|
|
|||
|
|
@ -25,29 +25,11 @@
|
|||
#include <dbus/dbus-internals.h>
|
||||
#include <expat.h>
|
||||
|
||||
static void*
|
||||
expat_malloc (size_t size)
|
||||
{
|
||||
return dbus_malloc (size);
|
||||
}
|
||||
|
||||
static void*
|
||||
expat_realloc (void *ptr, size_t size)
|
||||
{
|
||||
return dbus_realloc (ptr, size);
|
||||
}
|
||||
|
||||
static void
|
||||
expat_free (void *ptr)
|
||||
{
|
||||
dbus_free (ptr);
|
||||
}
|
||||
|
||||
static XML_Memory_Handling_Suite memsuite =
|
||||
{
|
||||
expat_malloc,
|
||||
expat_realloc,
|
||||
expat_free
|
||||
dbus_malloc,
|
||||
dbus_realloc,
|
||||
dbus_free
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
|
|
|||
|
|
@ -285,47 +285,18 @@ do_load (const DBusString *full_path,
|
|||
}
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
check_oom_loading (const DBusString *full_path,
|
||||
Validity validity)
|
||||
typedef struct
|
||||
{
|
||||
int approx_mallocs;
|
||||
const DBusString *full_path;
|
||||
Validity validity;
|
||||
} LoaderOomData;
|
||||
|
||||
/* Run once to see about how many mallocs are involved */
|
||||
|
||||
_dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
|
||||
static dbus_bool_t
|
||||
check_loader_oom_func (void *data)
|
||||
{
|
||||
LoaderOomData *d = data;
|
||||
|
||||
if (!do_load (full_path, validity, FALSE))
|
||||
return FALSE;
|
||||
|
||||
approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
|
||||
|
||||
_dbus_verbose ("=================\nabout %d mallocs total\n=================\n",
|
||||
approx_mallocs);
|
||||
|
||||
approx_mallocs += 10; /* fudge factor */
|
||||
|
||||
/* Now run failing each malloc */
|
||||
|
||||
while (approx_mallocs >= 0)
|
||||
{
|
||||
|
||||
_dbus_set_fail_alloc_counter (approx_mallocs);
|
||||
|
||||
_dbus_verbose ("\n===\n(will fail malloc %d)\n===\n",
|
||||
approx_mallocs);
|
||||
|
||||
if (!do_load (full_path, validity, TRUE))
|
||||
return FALSE;
|
||||
|
||||
approx_mallocs -= 1;
|
||||
}
|
||||
|
||||
_dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
|
||||
|
||||
_dbus_verbose ("=================\n all iterations passed\n=================\n");
|
||||
|
||||
return TRUE;
|
||||
return do_load (d->full_path, d->validity, TRUE);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
|
|
@ -376,6 +347,7 @@ process_test_subdir (const DBusString *test_base_dir,
|
|||
while (_dbus_directory_get_next_file (dir, &filename, &error))
|
||||
{
|
||||
DBusString full_path;
|
||||
LoaderOomData d;
|
||||
|
||||
if (!_dbus_string_init (&full_path, _DBUS_INT_MAX))
|
||||
_dbus_assert_not_reached ("couldn't init string");
|
||||
|
|
@ -407,7 +379,9 @@ process_test_subdir (const DBusString *test_base_dir,
|
|||
(validity == INVALID ? "invalid" :
|
||||
(validity == UNKNOWN ? "unknown" : "???")));
|
||||
|
||||
if (!check_oom_loading (&full_path, validity))
|
||||
d.full_path = &full_path;
|
||||
d.validity = validity;
|
||||
if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d))
|
||||
_dbus_assert_not_reached ("test failed");
|
||||
|
||||
_dbus_string_free (&full_path);
|
||||
|
|
|
|||
|
|
@ -916,49 +916,42 @@ check_hello_connection (BusContext *context)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Check1Func func;
|
||||
BusContext *context;
|
||||
} Check1Data;
|
||||
|
||||
static dbus_bool_t
|
||||
check_oom_check1_func (void *data)
|
||||
{
|
||||
Check1Data *d = data;
|
||||
|
||||
if (! (* d->func) (d->context))
|
||||
return FALSE;
|
||||
|
||||
if (!check_no_leftovers (d->context))
|
||||
{
|
||||
_dbus_warn ("Messages were left over, should be covered by test suite");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
check1_try_iterations (BusContext *context,
|
||||
const char *description,
|
||||
Check1Func func)
|
||||
{
|
||||
int approx_mallocs;
|
||||
Check1Data d;
|
||||
|
||||
/* Run once to see about how many mallocs are involved */
|
||||
|
||||
_dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
|
||||
|
||||
if (! (*func) (context))
|
||||
d.func = func;
|
||||
d.context = context;
|
||||
|
||||
if (!_dbus_test_oom_handling (description, check_oom_check1_func,
|
||||
&d))
|
||||
_dbus_assert_not_reached ("test failed");
|
||||
|
||||
approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
|
||||
|
||||
_dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n",
|
||||
description, approx_mallocs);
|
||||
|
||||
approx_mallocs += 10; /* fudge factor */
|
||||
|
||||
/* Now run failing each malloc */
|
||||
|
||||
while (approx_mallocs >= 0)
|
||||
{
|
||||
_dbus_set_fail_alloc_counter (approx_mallocs);
|
||||
|
||||
_dbus_verbose ("\n===\n %s: (will fail malloc %d)\n===\n",
|
||||
description, approx_mallocs);
|
||||
|
||||
if (! (*func) (context))
|
||||
_dbus_assert_not_reached ("test failed");
|
||||
|
||||
if (!check_no_leftovers (context))
|
||||
_dbus_assert_not_reached ("Messages were left over, should be covered by test suite");
|
||||
|
||||
approx_mallocs -= 1;
|
||||
}
|
||||
|
||||
_dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
|
||||
|
||||
_dbus_verbose ("=================\n%s: all iterations passed\n=================\n",
|
||||
description);
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
|
|
|
|||
|
|
@ -267,7 +267,6 @@ bus_test_client_listed (DBusConnection *connection)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bus_test_flush_bus (BusContext *context)
|
||||
{
|
||||
|
|
@ -276,11 +275,14 @@ bus_test_flush_bus (BusContext *context)
|
|||
* one end of the debug pipe to come out the other end...
|
||||
* a more robust setup would be good. Blocking on the other
|
||||
* end of pipes we've pushed data into or something.
|
||||
* A simple hack might be to just make the debug server always
|
||||
* poll for read on the other end of the pipe after writing.
|
||||
*/
|
||||
|
||||
while (bus_loop_iterate (FALSE))
|
||||
;
|
||||
#if 0
|
||||
_dbus_sleep_milliseconds (15);
|
||||
#endif
|
||||
while (bus_loop_iterate (FALSE))
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,8 +244,8 @@ elif test x$with_xml = xlibxml; then
|
|||
fi
|
||||
else
|
||||
### expat is the default because libxml can't currently survive
|
||||
### our brutal OOM-handling unit test setup. Need to find the
|
||||
### bugs and submit to DV
|
||||
### our brutal OOM-handling unit test setup.
|
||||
### http://bugzilla.gnome.org/show_bug.cgi?id=109368
|
||||
if $have_expat ; then
|
||||
with_xml=expat
|
||||
dbus_use_expat=true
|
||||
|
|
|
|||
|
|
@ -1241,14 +1241,14 @@ process_auth (DBusAuth *auth,
|
|||
_dbus_string_free (&mech);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!_dbus_string_init (&decoded_response, _DBUS_INT_MAX))
|
||||
{
|
||||
_dbus_string_free (&mech);
|
||||
_dbus_string_free (&base64_response);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!_dbus_string_copy_len (args, 0, i, &mech, 0))
|
||||
goto failed;
|
||||
|
||||
|
|
@ -1258,7 +1258,7 @@ process_auth (DBusAuth *auth,
|
|||
if (!_dbus_string_base64_decode (&base64_response, 0,
|
||||
&decoded_response, 0))
|
||||
goto failed;
|
||||
|
||||
|
||||
auth->mech = find_mech (&mech);
|
||||
if (auth->mech != NULL)
|
||||
{
|
||||
|
|
@ -1274,7 +1274,7 @@ process_auth (DBusAuth *auth,
|
|||
{
|
||||
/* Unsupported mechanism */
|
||||
if (!send_rejected (auth))
|
||||
return FALSE;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_dbus_string_free (&mech);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <dbus/dbus-connection.h>
|
||||
|
||||
DBUS_BEGIN_DECLS;
|
||||
|
||||
dbus_bool_t dbus_bus_register (DBusConnection *connection,
|
||||
DBusError *error);
|
||||
dbus_bool_t dbus_bus_set_base_service (DBusConnection *connection,
|
||||
|
|
@ -42,6 +44,6 @@ dbus_bool_t dbus_bus_service_exists (DBusConnection *connection,
|
|||
const char *service_name,
|
||||
DBusError *error);
|
||||
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
#endif /* DBUS_BUS_H */
|
||||
|
|
|
|||
|
|
@ -292,4 +292,85 @@ _dbus_type_to_string (int type)
|
|||
}
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
run_failing_each_malloc (int n_mallocs,
|
||||
const char *description,
|
||||
DBusTestMemoryFunction func,
|
||||
void *data)
|
||||
{
|
||||
n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
|
||||
|
||||
while (n_mallocs >= 0)
|
||||
{
|
||||
_dbus_set_fail_alloc_counter (n_mallocs);
|
||||
|
||||
_dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
|
||||
description, n_mallocs,
|
||||
_dbus_get_fail_alloc_failures ());
|
||||
|
||||
if (!(* func) (data))
|
||||
return FALSE;
|
||||
|
||||
n_mallocs -= 1;
|
||||
}
|
||||
|
||||
_dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests how well the given function responds to out-of-memory
|
||||
* situations. Calls the function repeatedly, failing a different
|
||||
* call to malloc() each time. If the function ever returns #FALSE,
|
||||
* the test fails. The function should return #TRUE whenever something
|
||||
* valid (such as returning an error, or succeeding) occurs, and #FALSE
|
||||
* if it gets confused in some way.
|
||||
*
|
||||
* @param description description of the test used in verbose output
|
||||
* @param func function to call
|
||||
* @param data data to pass to function
|
||||
* @returns #TRUE if the function never returns FALSE
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_test_oom_handling (const char *description,
|
||||
DBusTestMemoryFunction func,
|
||||
void *data)
|
||||
{
|
||||
int approx_mallocs;
|
||||
|
||||
/* Run once to see about how many mallocs are involved */
|
||||
|
||||
_dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
|
||||
|
||||
if (!(* func) (data))
|
||||
return FALSE;
|
||||
|
||||
approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
|
||||
|
||||
_dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n",
|
||||
description, approx_mallocs);
|
||||
|
||||
_dbus_set_fail_alloc_failures (1);
|
||||
if (!run_failing_each_malloc (approx_mallocs, description, func, data))
|
||||
return FALSE;
|
||||
|
||||
_dbus_set_fail_alloc_failures (2);
|
||||
if (!run_failing_each_malloc (approx_mallocs, description, func, data))
|
||||
return FALSE;
|
||||
|
||||
_dbus_set_fail_alloc_failures (3);
|
||||
if (!run_failing_each_malloc (approx_mallocs, description, func, data))
|
||||
return FALSE;
|
||||
|
||||
_dbus_set_fail_alloc_failures (4);
|
||||
if (!run_failing_each_malloc (approx_mallocs, description, func, data))
|
||||
return FALSE;
|
||||
|
||||
_dbus_verbose ("=================\n%s: all iterations passed\n=================\n",
|
||||
description);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -170,9 +170,16 @@ extern const char _dbus_no_memory_message[];
|
|||
/* Memory debugging */
|
||||
void _dbus_set_fail_alloc_counter (int until_next_fail);
|
||||
int _dbus_get_fail_alloc_counter (void);
|
||||
void _dbus_set_fail_alloc_failures (int failures_per_failure);
|
||||
int _dbus_get_fail_alloc_failures (void);
|
||||
dbus_bool_t _dbus_decrement_fail_alloc_counter (void);
|
||||
dbus_bool_t _dbus_disable_mem_pools (void);
|
||||
int _dbus_get_malloc_blocks_outstanding (void);
|
||||
|
||||
typedef dbus_bool_t (* DBusTestMemoryFunction) (void *data);
|
||||
dbus_bool_t _dbus_test_oom_handling (const char *description,
|
||||
DBusTestMemoryFunction func,
|
||||
void *data);
|
||||
#else
|
||||
#define _dbus_set_fail_alloc_counter(n)
|
||||
#define _dbus_get_fail_alloc_counter _DBUS_INT_MAX
|
||||
|
|
|
|||
|
|
@ -76,9 +76,11 @@
|
|||
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
static dbus_bool_t debug_initialized = FALSE;
|
||||
static int fail_counts = -1;
|
||||
static int fail_nth = -1;
|
||||
static size_t fail_size = 0;
|
||||
static int fail_alloc_counter = _DBUS_INT_MAX;
|
||||
static int n_failures_per_failure = 1;
|
||||
static int n_failures_this_failure = 0;
|
||||
static dbus_bool_t guards = FALSE;
|
||||
static dbus_bool_t disable_mem_pools = FALSE;
|
||||
static dbus_bool_t backtrace_on_fail_alloc = FALSE;
|
||||
|
|
@ -106,9 +108,9 @@ _dbus_initialize_malloc_debug (void)
|
|||
|
||||
if (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH") != NULL)
|
||||
{
|
||||
fail_counts = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH"));
|
||||
fail_alloc_counter = fail_counts;
|
||||
_dbus_verbose ("Will fail malloc every %d times\n", fail_counts);
|
||||
fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH"));
|
||||
fail_alloc_counter = fail_nth;
|
||||
_dbus_verbose ("Will fail malloc every %d times\n", fail_nth);
|
||||
}
|
||||
|
||||
if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL)
|
||||
|
|
@ -184,6 +186,30 @@ _dbus_get_fail_alloc_counter (void)
|
|||
return fail_alloc_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how many mallocs to fail when the fail alloc counter reaches
|
||||
* 0.
|
||||
*
|
||||
* @param number to fail
|
||||
*/
|
||||
void
|
||||
_dbus_set_fail_alloc_failures (int failures_per_failure)
|
||||
{
|
||||
n_failures_per_failure = failures_per_failure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of failures we'll have when the fail malloc
|
||||
* counter reaches 0.
|
||||
*
|
||||
* @returns number of failures planned
|
||||
*/
|
||||
int
|
||||
_dbus_get_fail_alloc_failures (void)
|
||||
{
|
||||
return n_failures_per_failure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when about to alloc some memory; if
|
||||
* it returns #TRUE, then the allocation should
|
||||
|
|
@ -199,14 +225,23 @@ _dbus_decrement_fail_alloc_counter (void)
|
|||
|
||||
if (fail_alloc_counter <= 0)
|
||||
{
|
||||
if (fail_counts >= 0)
|
||||
fail_alloc_counter = fail_counts;
|
||||
else
|
||||
fail_alloc_counter = _DBUS_INT_MAX;
|
||||
|
||||
_dbus_verbose ("reset fail alloc counter to %d\n", fail_alloc_counter);
|
||||
if (backtrace_on_fail_alloc)
|
||||
_dbus_print_backtrace ();
|
||||
|
||||
_dbus_verbose ("failure %d\n", n_failures_this_failure);
|
||||
|
||||
n_failures_this_failure += 1;
|
||||
if (n_failures_this_failure >= n_failures_per_failure)
|
||||
{
|
||||
if (fail_nth >= 0)
|
||||
fail_alloc_counter = fail_nth;
|
||||
else
|
||||
fail_alloc_counter = _DBUS_INT_MAX;
|
||||
|
||||
n_failures_this_failure = 0;
|
||||
|
||||
_dbus_verbose ("reset fail alloc counter to %d\n", fail_alloc_counter);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2108,15 +2108,22 @@ _dbus_string_base64_decode (const DBusString *source,
|
|||
*/
|
||||
|
||||
if (pad_count < 1)
|
||||
_dbus_string_append_byte (&result,
|
||||
triplet >> 16);
|
||||
{
|
||||
if (!_dbus_string_append_byte (&result,
|
||||
triplet >> 16))
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (pad_count < 2)
|
||||
_dbus_string_append_byte (&result,
|
||||
(triplet >> 8) & 0xff);
|
||||
{
|
||||
if (!_dbus_string_append_byte (&result,
|
||||
(triplet >> 8) & 0xff))
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_dbus_string_append_byte (&result,
|
||||
triplet & 0xff);
|
||||
if (!_dbus_string_append_byte (&result,
|
||||
triplet & 0xff))
|
||||
goto failed;
|
||||
|
||||
sextet_count = 0;
|
||||
pad_count = 0;
|
||||
|
|
@ -2136,6 +2143,11 @@ _dbus_string_base64_decode (const DBusString *source,
|
|||
_dbus_string_free (&result);
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed:
|
||||
_dbus_string_free (&result);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
7
doc/TODO
7
doc/TODO
|
|
@ -39,3 +39,10 @@
|
|||
|
||||
- Automatic service activation, should probably be done through a message flag.
|
||||
|
||||
- Disconnecting the remote end on invalid UTF-8 is probably not a good
|
||||
idea. The definitiion of "valid" is slightly fuzzy. I think it might
|
||||
be better to just silently "fix" the UTF-8, or perhaps return an error.
|
||||
|
||||
- We might consider returning a "no such operation" error in dbus-connection.c
|
||||
for unhandled messages.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue