mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 04:08:12 +02:00
2003-03-23 Havoc Pennington <hp@pobox.com>
* dbus/dbus-threads.c (dbus_mutex_new, dbus_condvar_new): with DBUS_BUILD_TESTS, actually alloc/free a block of memory for the mutex, so we can check for proper memory management and OOM handling. * dbus/dbus-dataslot.c: remove the mutex from DBusDataSlotAllocator and lock it manually when using it, to simplify fitting it into the global slots framework. * dbus/dbus-threads.c (init_static_locks): rework how we're handling global locks so they are easily shut down. * bus/policy.c (bus_policy_append_rule): fix * bus/test-main.c (main): check for memleaks * dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): make test suite check for memleaks * dbus/dbus-memory.c: add support in test mode for tracking number of outstanding blocks
This commit is contained in:
parent
a26607ab68
commit
c3af5ccdbc
18 changed files with 511 additions and 235 deletions
24
ChangeLog
24
ChangeLog
|
|
@ -1,3 +1,27 @@
|
|||
2003-03-23 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-threads.c (dbus_mutex_new, dbus_condvar_new): with
|
||||
DBUS_BUILD_TESTS, actually alloc/free a block of memory for
|
||||
the mutex, so we can check for proper memory management
|
||||
and OOM handling.
|
||||
|
||||
* dbus/dbus-dataslot.c: remove the mutex from
|
||||
DBusDataSlotAllocator and lock it manually when using it,
|
||||
to simplify fitting it into the global slots framework.
|
||||
|
||||
* dbus/dbus-threads.c (init_static_locks): rework how we're
|
||||
handling global locks so they are easily shut down.
|
||||
|
||||
* bus/policy.c (bus_policy_append_rule): fix
|
||||
|
||||
* bus/test-main.c (main): check for memleaks
|
||||
|
||||
* dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): make
|
||||
test suite check for memleaks
|
||||
|
||||
* dbus/dbus-memory.c: add support in test mode for tracking
|
||||
number of outstanding blocks
|
||||
|
||||
2003-03-23 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* bus/policy.c, bus/bus.c, bus/connection.c: implement allow/deny
|
||||
|
|
|
|||
10
bus/policy.c
10
bus/policy.c
|
|
@ -73,6 +73,10 @@ bus_policy_rule_unref (BusPolicyRule *rule)
|
|||
case BUS_POLICY_RULE_OWN:
|
||||
dbus_free (rule->d.own.service_name);
|
||||
break;
|
||||
case BUS_POLICY_RULE_USER:
|
||||
case BUS_POLICY_RULE_GROUP:
|
||||
_dbus_assert_not_reached ("invalid rule");
|
||||
break;
|
||||
}
|
||||
|
||||
dbus_free (rule);
|
||||
|
|
@ -203,6 +207,10 @@ bus_policy_optimize (BusPolicy *policy)
|
|||
remove_preceding =
|
||||
rule->d.own.service_name == NULL;
|
||||
break;
|
||||
case BUS_POLICY_RULE_USER:
|
||||
case BUS_POLICY_RULE_GROUP:
|
||||
_dbus_assert_not_reached ("invalid rule");
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove_preceding)
|
||||
|
|
@ -220,7 +228,7 @@ dbus_bool_t
|
|||
bus_policy_append_rule (BusPolicy *policy,
|
||||
BusPolicyRule *rule)
|
||||
{
|
||||
if (!_dbus_list_append (policy->rules, rule))
|
||||
if (!_dbus_list_append (&policy->rules, rule))
|
||||
return FALSE;
|
||||
|
||||
bus_policy_rule_ref (rule);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <dbus/dbus-string.h>
|
||||
#include <dbus/dbus-sysdeps.h>
|
||||
#include <dbus/dbus-internals.h>
|
||||
|
||||
static void
|
||||
die (const char *failure)
|
||||
|
|
@ -55,6 +56,16 @@ main (int argc, char **argv)
|
|||
if (!bus_dispatch_test (&test_data_dir))
|
||||
die ("dispatch");
|
||||
|
||||
dbus_shutdown ();
|
||||
|
||||
printf ("%s: checking for memleaks\n", argv[0]);
|
||||
if (_dbus_get_malloc_blocks_outstanding () != 0)
|
||||
{
|
||||
_dbus_warn ("%d dbus_malloc blocks were not freed\n",
|
||||
_dbus_get_malloc_blocks_outstanding ());
|
||||
die ("memleaks");
|
||||
}
|
||||
|
||||
printf ("%s: Success\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -63,24 +63,12 @@ static int bus_data_slot_refcount = 0;
|
|||
/**
|
||||
* Lock for bus_data_slot and bus_data_slot_refcount
|
||||
*/
|
||||
static DBusMutex *slot_lock;
|
||||
|
||||
/**
|
||||
* Initialize the mutex used for bus_data_slot
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_bus_init_lock (void)
|
||||
{
|
||||
slot_lock = dbus_mutex_new ();
|
||||
return slot_lock;
|
||||
}
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (bus);
|
||||
|
||||
static dbus_bool_t
|
||||
data_slot_ref (void)
|
||||
{
|
||||
dbus_mutex_lock (slot_lock);
|
||||
_DBUS_LOCK (bus);
|
||||
|
||||
if (bus_data_slot < 0)
|
||||
{
|
||||
|
|
@ -88,7 +76,7 @@ data_slot_ref (void)
|
|||
|
||||
if (bus_data_slot < 0)
|
||||
{
|
||||
dbus_mutex_unlock (slot_lock);
|
||||
_DBUS_UNLOCK (bus);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +85,7 @@ data_slot_ref (void)
|
|||
|
||||
bus_data_slot_refcount += 1;
|
||||
|
||||
dbus_mutex_unlock (slot_lock);
|
||||
_DBUS_UNLOCK (bus);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -105,7 +93,7 @@ data_slot_ref (void)
|
|||
static void
|
||||
data_slot_unref (void)
|
||||
{
|
||||
dbus_mutex_lock (slot_lock);
|
||||
_DBUS_LOCK (bus);
|
||||
|
||||
_dbus_assert (bus_data_slot_refcount > 0);
|
||||
_dbus_assert (bus_data_slot >= 0);
|
||||
|
|
@ -118,7 +106,7 @@ data_slot_unref (void)
|
|||
bus_data_slot = -1;
|
||||
}
|
||||
|
||||
dbus_mutex_unlock (slot_lock);
|
||||
_DBUS_UNLOCK (bus);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -2472,21 +2472,7 @@ dbus_connection_unregister_handler (DBusConnection *connection,
|
|||
}
|
||||
|
||||
static DBusDataSlotAllocator slot_allocator;
|
||||
|
||||
/**
|
||||
* Initialize the mutex used for #DBusConnection data
|
||||
* slot reservations.
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_connection_slots_init_lock (void)
|
||||
{
|
||||
if (!_dbus_data_slot_allocator_init (&slot_allocator))
|
||||
return NULL;
|
||||
else
|
||||
return slot_allocator.lock;
|
||||
}
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
|
||||
|
||||
/**
|
||||
* Allocates an integer ID to be used for storing application-specific
|
||||
|
|
@ -2501,7 +2487,8 @@ _dbus_connection_slots_init_lock (void)
|
|||
int
|
||||
dbus_connection_allocate_data_slot (void)
|
||||
{
|
||||
return _dbus_data_slot_allocator_alloc (&slot_allocator);
|
||||
return _dbus_data_slot_allocator_alloc (&slot_allocator,
|
||||
_DBUS_LOCK_NAME (connection_slots));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -46,11 +46,9 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
|
|||
allocator->allocated_slots = NULL;
|
||||
allocator->n_allocated_slots = 0;
|
||||
allocator->n_used_slots = 0;
|
||||
allocator->lock = dbus_mutex_new ();
|
||||
if (allocator->lock == NULL)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
allocator->lock = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -62,16 +60,26 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
|
|||
* DBusDataSlotAllocator so it isn't cut-and-pasted everywhere.
|
||||
*
|
||||
* @param allocator the allocator
|
||||
* @param mutex the lock for this allocator
|
||||
* @returns the integer ID, or -1 on failure
|
||||
*/
|
||||
int
|
||||
_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator)
|
||||
_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
|
||||
DBusMutex *mutex)
|
||||
{
|
||||
int slot;
|
||||
|
||||
if (!dbus_mutex_lock (allocator->lock))
|
||||
|
||||
if (!dbus_mutex_lock (mutex))
|
||||
return -1;
|
||||
|
||||
if (allocator->n_allocated_slots == 0)
|
||||
{
|
||||
_dbus_assert (allocator->lock == NULL);
|
||||
allocator->lock = mutex;
|
||||
}
|
||||
else
|
||||
_dbus_assert (allocator->lock == mutex);
|
||||
|
||||
if (allocator->n_used_slots < allocator->n_allocated_slots)
|
||||
{
|
||||
slot = 0;
|
||||
|
|
@ -128,27 +136,34 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator)
|
|||
*/
|
||||
void
|
||||
_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
|
||||
int slot)
|
||||
int slot)
|
||||
{
|
||||
dbus_mutex_lock (allocator->lock);
|
||||
|
||||
|
||||
_dbus_assert (slot < allocator->n_allocated_slots);
|
||||
_dbus_assert (allocator->allocated_slots[slot] == slot);
|
||||
|
||||
allocator->allocated_slots[slot] = -1;
|
||||
allocator->n_used_slots -= 1;
|
||||
|
||||
if (allocator->n_used_slots == 0)
|
||||
{
|
||||
dbus_free (allocator->allocated_slots);
|
||||
allocator->allocated_slots = NULL;
|
||||
allocator->n_allocated_slots = 0;
|
||||
}
|
||||
|
||||
_dbus_verbose ("Freed slot %d on allocator %p total %d allocated %d used\n",
|
||||
slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots);
|
||||
|
||||
dbus_mutex_unlock (allocator->lock);
|
||||
if (allocator->n_used_slots == 0)
|
||||
{
|
||||
DBusMutex *mutex = allocator->lock;
|
||||
|
||||
dbus_free (allocator->allocated_slots);
|
||||
allocator->allocated_slots = NULL;
|
||||
allocator->n_allocated_slots = 0;
|
||||
allocator->lock = NULL;
|
||||
|
||||
dbus_mutex_unlock (mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_mutex_unlock (allocator->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -320,12 +335,17 @@ _dbus_data_slot_test (void)
|
|||
int i;
|
||||
DBusFreeFunction old_free_func;
|
||||
void *old_data;
|
||||
DBusMutex *mutex;
|
||||
|
||||
if (!_dbus_data_slot_allocator_init (&allocator))
|
||||
_dbus_assert_not_reached ("no memory for allocator");
|
||||
|
||||
_dbus_data_slot_list_init (&list);
|
||||
|
||||
mutex = dbus_mutex_new ();
|
||||
if (mutex == NULL)
|
||||
_dbus_assert_not_reached ("failed to alloc mutex");
|
||||
|
||||
#define N_SLOTS 100
|
||||
|
||||
i = 0;
|
||||
|
|
@ -335,7 +355,7 @@ _dbus_data_slot_test (void)
|
|||
* allocation, but it simplifies things to rely on it
|
||||
* here.
|
||||
*/
|
||||
if (_dbus_data_slot_allocator_alloc (&allocator) != i)
|
||||
if (_dbus_data_slot_allocator_alloc (&allocator, mutex) != i)
|
||||
_dbus_assert_not_reached ("did not allocate slots in numeric order\n");
|
||||
|
||||
++i;
|
||||
|
|
@ -394,6 +414,8 @@ _dbus_data_slot_test (void)
|
|||
_dbus_data_slot_allocator_free (&allocator, i);
|
||||
++i;
|
||||
}
|
||||
|
||||
dbus_mutex_free (mutex);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,23 +53,24 @@ struct DBusDataSlotList
|
|||
int n_slots; /**< Slots we have storage for in data_slots */
|
||||
};
|
||||
|
||||
dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator);
|
||||
int _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator);
|
||||
void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
|
||||
int slot_id);
|
||||
dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator);
|
||||
int _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
|
||||
DBusMutex *mutex);
|
||||
void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
|
||||
int slot_id);
|
||||
void _dbus_data_slot_list_init (DBusDataSlotList *list);
|
||||
dbus_bool_t _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
|
||||
DBusDataSlotList *list,
|
||||
int slot,
|
||||
void *data,
|
||||
DBusFreeFunction free_data_func,
|
||||
DBusFreeFunction *old_free_func,
|
||||
void **old_data);
|
||||
void* _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
|
||||
DBusDataSlotList *list,
|
||||
int slot);
|
||||
void _dbus_data_slot_list_free (DBusDataSlotList *list);
|
||||
|
||||
void _dbus_data_slot_list_init (DBusDataSlotList *list);
|
||||
dbus_bool_t _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
|
||||
DBusDataSlotList *list,
|
||||
int slot,
|
||||
void *data,
|
||||
DBusFreeFunction free_data_func,
|
||||
DBusFreeFunction *old_free_func,
|
||||
void **old_data);
|
||||
void* _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
|
||||
DBusDataSlotList *list,
|
||||
int slot);
|
||||
void _dbus_data_slot_list_free (DBusDataSlotList *list);
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,41 @@
|
|||
* a DBusList.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def _DBUS_LOCK_NAME
|
||||
*
|
||||
* Expands to name of a global lock variable.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def _DBUS_DEFINE_GLOBAL_LOCK
|
||||
*
|
||||
* Defines a global lock variable with the given name.
|
||||
* The lock must be added to the list to initialize
|
||||
* in dbus_threads_init().
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def _DBUS_DECLARE_GLOBAL_LOCK
|
||||
*
|
||||
* Expands to declaration of a global lock defined
|
||||
* with _DBUS_DEFINE_GLOBAL_LOCK.
|
||||
* The lock must be added to the list to initialize
|
||||
* in dbus_threads_init().
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def _DBUS_LOCK
|
||||
*
|
||||
* Locks a global lock
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def _DBUS_UNLOCK
|
||||
*
|
||||
* Unlocks a global lock
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fixed "out of memory" error message, just to avoid
|
||||
* making up a different string every time and wasting
|
||||
|
|
|
|||
|
|
@ -169,10 +169,11 @@ extern const char _dbus_no_memory_message[];
|
|||
|
||||
#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);
|
||||
dbus_bool_t _dbus_disable_mem_pools (void);
|
||||
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);
|
||||
dbus_bool_t _dbus_disable_mem_pools (void);
|
||||
int _dbus_get_malloc_blocks_outstanding (void);
|
||||
#else
|
||||
#define _dbus_set_fail_alloc_counter(n)
|
||||
#define _dbus_get_fail_alloc_counter _DBUS_INT_MAX
|
||||
|
|
@ -180,18 +181,32 @@ dbus_bool_t _dbus_disable_mem_pools (void);
|
|||
/* These are constant expressions so that blocks
|
||||
* they protect should be optimized away
|
||||
*/
|
||||
#define _dbus_decrement_fail_alloc_counter() FALSE
|
||||
#define _dbus_disable_mem_pools() FALSE
|
||||
#define _dbus_decrement_fail_alloc_counter() (FALSE)
|
||||
#define _dbus_disable_mem_pools() (FALSE)
|
||||
#define _dbus_get_malloc_blocks_outstanding (0)
|
||||
#endif /* !DBUS_BUILD_TESTS */
|
||||
|
||||
typedef void (* DBusShutdownFunction) (void *data);
|
||||
dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function,
|
||||
void *data);
|
||||
|
||||
extern int _dbus_current_generation;
|
||||
|
||||
/* Thread initializers */
|
||||
DBusMutex *_dbus_list_init_lock (void);
|
||||
DBusMutex *_dbus_connection_slots_init_lock (void);
|
||||
DBusMutex *_dbus_server_slots_init_lock (void);
|
||||
DBusMutex *_dbus_atomic_init_lock (void);
|
||||
DBusMutex *_dbus_message_handler_init_lock (void);
|
||||
DBusMutex *_dbus_user_info_init_lock (void);
|
||||
DBusMutex *_dbus_bus_init_lock (void);
|
||||
#define _DBUS_LOCK_NAME(name) _dbus_lock_##name
|
||||
#define _DBUS_DECLARE_GLOBAL_LOCK(name) extern DBusMutex *_dbus_lock_##name
|
||||
#define _DBUS_DEFINE_GLOBAL_LOCK(name) DBusMutex *_dbus_lock_##name
|
||||
#define _DBUS_LOCK(name) dbus_mutex_lock (_dbus_lock_##name)
|
||||
#define _DBUS_UNLOCK(name) dbus_mutex_unlock (_dbus_lock_##name)
|
||||
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (list);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (atomic);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (message_handler);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (user_info);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (bus);
|
||||
#define _DBUS_N_GLOBAL_LOCKS (7)
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,19 +35,7 @@
|
|||
*/
|
||||
|
||||
static DBusMemPool *list_pool;
|
||||
static DBusMutex *list_pool_lock = NULL;
|
||||
|
||||
/**
|
||||
* Initializes the global mutex used for allocating list nodes.
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_list_init_lock (void)
|
||||
{
|
||||
list_pool_lock = dbus_mutex_new ();
|
||||
return list_pool_lock;
|
||||
}
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (list);
|
||||
|
||||
/**
|
||||
* @defgroup DBusListInternals Linked list implementation details
|
||||
|
|
@ -67,7 +55,7 @@ alloc_link (void *data)
|
|||
{
|
||||
DBusList *link;
|
||||
|
||||
if (!dbus_mutex_lock (list_pool_lock))
|
||||
if (!_DBUS_LOCK (list))
|
||||
return NULL;
|
||||
|
||||
if (!list_pool)
|
||||
|
|
@ -76,7 +64,7 @@ alloc_link (void *data)
|
|||
|
||||
if (list_pool == NULL)
|
||||
{
|
||||
dbus_mutex_unlock (list_pool_lock);
|
||||
_DBUS_UNLOCK (list);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -85,7 +73,7 @@ alloc_link (void *data)
|
|||
if (link)
|
||||
link->data = data;
|
||||
|
||||
dbus_mutex_unlock (list_pool_lock);
|
||||
_DBUS_UNLOCK (list);
|
||||
|
||||
return link;
|
||||
}
|
||||
|
|
@ -93,13 +81,13 @@ alloc_link (void *data)
|
|||
static void
|
||||
free_link (DBusList *link)
|
||||
{
|
||||
dbus_mutex_lock (list_pool_lock);
|
||||
_DBUS_LOCK (list);
|
||||
if (_dbus_mem_pool_dealloc (list_pool, link))
|
||||
{
|
||||
_dbus_mem_pool_free (list_pool);
|
||||
list_pool = NULL;
|
||||
}
|
||||
dbus_mutex_unlock (list_pool_lock);
|
||||
_DBUS_UNLOCK (list);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "dbus-memory.h"
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-sysdeps.h"
|
||||
#include "dbus-list.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
|
@ -81,6 +82,7 @@ static int fail_alloc_counter = _DBUS_INT_MAX;
|
|||
static dbus_bool_t guards = FALSE;
|
||||
static dbus_bool_t disable_mem_pools = FALSE;
|
||||
static dbus_bool_t backtrace_on_fail_alloc = FALSE;
|
||||
static int n_blocks_outstanding = 0;
|
||||
|
||||
/** value stored in guard padding for debugging buffer overrun */
|
||||
#define GUARD_VALUE 0xdeadbeef
|
||||
|
|
@ -215,6 +217,17 @@ _dbus_decrement_fail_alloc_counter (void)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of outstanding malloc()'d blocks.
|
||||
*
|
||||
* @returns number of blocks
|
||||
*/
|
||||
int
|
||||
_dbus_get_malloc_blocks_outstanding (void)
|
||||
{
|
||||
return n_blocks_outstanding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where the block came from.
|
||||
*/
|
||||
|
|
@ -372,11 +385,22 @@ dbus_malloc (size_t bytes)
|
|||
void *block;
|
||||
|
||||
block = malloc (bytes + GUARD_EXTRA_SIZE);
|
||||
if (block)
|
||||
n_blocks_outstanding += 1;
|
||||
|
||||
return set_guards (block, bytes, SOURCE_MALLOC);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return malloc (bytes);
|
||||
{
|
||||
void *mem;
|
||||
mem = malloc (bytes);
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
if (mem)
|
||||
n_blocks_outstanding += 1;
|
||||
#endif
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -412,11 +436,21 @@ dbus_malloc0 (size_t bytes)
|
|||
void *block;
|
||||
|
||||
block = calloc (bytes + GUARD_EXTRA_SIZE, 1);
|
||||
if (block)
|
||||
n_blocks_outstanding += 1;
|
||||
return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return calloc (bytes, 1);
|
||||
{
|
||||
void *mem;
|
||||
mem = calloc (bytes, 1);
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
if (mem)
|
||||
n_blocks_outstanding += 1;
|
||||
#endif
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -462,9 +496,10 @@ dbus_realloc (void *memory,
|
|||
|
||||
block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
|
||||
bytes + GUARD_EXTRA_SIZE);
|
||||
|
||||
/* old guards shouldn't have moved */
|
||||
check_guards (((unsigned char*)block) + GUARD_START_OFFSET);
|
||||
|
||||
if (block)
|
||||
/* old guards shouldn't have moved */
|
||||
check_guards (((unsigned char*)block) + GUARD_START_OFFSET);
|
||||
|
||||
return set_guards (block, bytes, SOURCE_REALLOC);
|
||||
}
|
||||
|
|
@ -473,13 +508,23 @@ dbus_realloc (void *memory,
|
|||
void *block;
|
||||
|
||||
block = malloc (bytes + GUARD_EXTRA_SIZE);
|
||||
|
||||
if (block)
|
||||
n_blocks_outstanding += 1;
|
||||
|
||||
return set_guards (block, bytes, SOURCE_REALLOC_NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return realloc (memory, bytes);
|
||||
void *mem;
|
||||
mem = realloc (memory, bytes);
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
if (memory == NULL && mem != NULL)
|
||||
n_blocks_outstanding += 1;
|
||||
#endif
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -497,13 +542,28 @@ dbus_free (void *memory)
|
|||
{
|
||||
check_guards (memory);
|
||||
if (memory)
|
||||
free (((unsigned char*)memory) - GUARD_START_OFFSET);
|
||||
{
|
||||
n_blocks_outstanding -= 1;
|
||||
|
||||
_dbus_assert (n_blocks_outstanding >= 0);
|
||||
|
||||
free (((unsigned char*)memory) - GUARD_START_OFFSET);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (memory) /* we guarantee it's safe to free (NULL) */
|
||||
free (memory);
|
||||
{
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
n_blocks_outstanding -= 1;
|
||||
|
||||
_dbus_assert (n_blocks_outstanding >= 0);
|
||||
#endif
|
||||
|
||||
free (memory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -530,4 +590,89 @@ dbus_free_string_array (char **str_array)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _dbus_current_generation is used to track each
|
||||
* time that dbus_shutdown() is called, so we can
|
||||
* reinit things after it's been called. It is simply
|
||||
* incremented each time we shut down.
|
||||
*/
|
||||
int _dbus_current_generation = 1;
|
||||
|
||||
static DBusList *registered_globals = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DBusShutdownFunction func;
|
||||
void *data;
|
||||
} ShutdownClosure;
|
||||
|
||||
/**
|
||||
* The D-BUS library keeps some internal global variables, for example
|
||||
* to cache the username of the current process. This function is
|
||||
* used to free these global variables. It is really useful only for
|
||||
* leak-checking cleanliness and the like. WARNING: this function is
|
||||
* NOT thread safe, it must be called while NO other threads are using
|
||||
* D-BUS. You cannot continue using D-BUS after calling this function,
|
||||
* as it does things like free global mutexes created by
|
||||
* dbus_threads_init(). To use a D-BUS function after calling
|
||||
* dbus_shutdown(), you have to start over from scratch, e.g. calling
|
||||
* dbus_threads_init() again.
|
||||
*/
|
||||
void
|
||||
dbus_shutdown (void)
|
||||
{
|
||||
DBusList *link;
|
||||
|
||||
link = _dbus_list_get_first_link (®istered_globals);
|
||||
while (link != NULL)
|
||||
{
|
||||
ShutdownClosure *c = link->data;
|
||||
|
||||
(* c->func) (c->data);
|
||||
|
||||
dbus_free (c);
|
||||
|
||||
link = _dbus_list_get_next_link (®istered_globals, link);
|
||||
}
|
||||
|
||||
_dbus_list_clear (®istered_globals);
|
||||
|
||||
_dbus_current_generation += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a cleanup function to be called exactly once
|
||||
* the next time dbus_shutdown() is called.
|
||||
*
|
||||
* @param func the function
|
||||
* @param data data to pass to the function
|
||||
* @returns #FALSE on not enough memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_register_shutdown_func (DBusShutdownFunction func,
|
||||
void *data)
|
||||
{
|
||||
ShutdownClosure *c;
|
||||
|
||||
c = dbus_new (ShutdownClosure, 1);
|
||||
|
||||
if (c == NULL)
|
||||
return FALSE;
|
||||
|
||||
c->func = func;
|
||||
c->data = data;
|
||||
|
||||
/* We prepend, then shutdown the list in order, so
|
||||
* we shutdown last-registered stuff first which
|
||||
* is right.
|
||||
*/
|
||||
if (!_dbus_list_prepend (®istered_globals, c))
|
||||
{
|
||||
dbus_free (c);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ void dbus_free_string_array (char **str_array);
|
|||
|
||||
typedef void (* DBusFreeFunction) (void *memory);
|
||||
|
||||
void dbus_shutdown (void);
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
#endif /* DBUS_MEMORY_H */
|
||||
|
|
|
|||
|
|
@ -37,20 +37,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
static DBusMutex *message_handler_lock = NULL;
|
||||
|
||||
/**
|
||||
* Initializes the mutex used for threadsafe access to
|
||||
* #DBusMessageHandler objects.
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_message_handler_init_lock (void)
|
||||
{
|
||||
message_handler_lock = dbus_mutex_new ();
|
||||
return message_handler_lock;
|
||||
}
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (message_handler);
|
||||
|
||||
/**
|
||||
* @brief Internals of DBusMessageHandler
|
||||
|
|
@ -83,7 +70,7 @@ _dbus_message_handler_add_connection (DBusMessageHandler *handler,
|
|||
{
|
||||
dbus_bool_t res;
|
||||
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
/* This is a bit wasteful - we just put the connection in the list
|
||||
* once per time it's added. :-/
|
||||
*/
|
||||
|
|
@ -92,7 +79,7 @@ _dbus_message_handler_add_connection (DBusMessageHandler *handler,
|
|||
else
|
||||
res = TRUE;
|
||||
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -106,10 +93,10 @@ void
|
|||
_dbus_message_handler_remove_connection (DBusMessageHandler *handler,
|
||||
DBusConnection *connection)
|
||||
{
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
if (!_dbus_list_remove (&handler->connections, connection))
|
||||
_dbus_warn ("Function _dbus_message_handler_remove_connection() called when the connection hadn't been added\n");
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -131,10 +118,10 @@ _dbus_message_handler_handle_message (DBusMessageHandler *handler,
|
|||
DBusHandleMessageFunction function;
|
||||
void *user_data;
|
||||
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
function = handler->function;
|
||||
user_data = handler->user_data;
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
|
||||
/* This function doesn't ref handler/connection/message
|
||||
* since that's done in dbus_connection_dispatch().
|
||||
|
|
@ -205,11 +192,11 @@ dbus_message_handler_new (DBusHandleMessageFunction function,
|
|||
void
|
||||
dbus_message_handler_ref (DBusMessageHandler *handler)
|
||||
{
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
_dbus_assert (handler != NULL);
|
||||
|
||||
handler->refcount += 1;
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -223,7 +210,7 @@ dbus_message_handler_unref (DBusMessageHandler *handler)
|
|||
{
|
||||
int refcount;
|
||||
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
|
||||
_dbus_assert (handler != NULL);
|
||||
_dbus_assert (handler->refcount > 0);
|
||||
|
|
@ -231,7 +218,7 @@ dbus_message_handler_unref (DBusMessageHandler *handler)
|
|||
handler->refcount -= 1;
|
||||
refcount = handler->refcount;
|
||||
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
|
||||
if (refcount == 0)
|
||||
{
|
||||
|
|
@ -267,9 +254,9 @@ void*
|
|||
dbus_message_handler_get_data (DBusMessageHandler *handler)
|
||||
{
|
||||
void* user_data;
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
user_data = handler->user_data;
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
return user_data;
|
||||
}
|
||||
|
||||
|
|
@ -290,13 +277,13 @@ dbus_message_handler_set_data (DBusMessageHandler *handler,
|
|||
DBusFreeFunction old_free_func;
|
||||
void *old_user_data;
|
||||
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
old_free_func = handler->free_user_data;
|
||||
old_user_data = handler->user_data;
|
||||
|
||||
handler->user_data = user_data;
|
||||
handler->free_user_data = free_user_data;
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
|
||||
if (old_free_func)
|
||||
(* old_free_func) (old_user_data);
|
||||
|
|
@ -314,9 +301,9 @@ void
|
|||
dbus_message_handler_set_function (DBusMessageHandler *handler,
|
||||
DBusHandleMessageFunction function)
|
||||
{
|
||||
dbus_mutex_lock (message_handler_lock);
|
||||
_DBUS_LOCK (message_handler);
|
||||
handler->function = function;
|
||||
dbus_mutex_unlock (message_handler_lock);
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -589,21 +589,7 @@ dbus_server_get_n_connections (DBusServer *server)
|
|||
|
||||
|
||||
static DBusDataSlotAllocator slot_allocator;
|
||||
|
||||
/**
|
||||
* Initialize the mutex used for #DBusConnection data
|
||||
* slot reservations.
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_server_slots_init_lock (void)
|
||||
{
|
||||
if (!_dbus_data_slot_allocator_init (&slot_allocator))
|
||||
return NULL;
|
||||
else
|
||||
return slot_allocator.lock;
|
||||
}
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (server_slots);
|
||||
|
||||
/**
|
||||
* Allocates an integer ID to be used for storing application-specific
|
||||
|
|
@ -618,7 +604,8 @@ _dbus_server_slots_init_lock (void)
|
|||
int
|
||||
dbus_server_allocate_data_slot (void)
|
||||
{
|
||||
return _dbus_data_slot_allocator_alloc (&slot_allocator);
|
||||
return _dbus_data_slot_allocator_alloc (&slot_allocator,
|
||||
_DBUS_LOCK_NAME (server_slots));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1232,17 +1232,22 @@ _dbus_credentials_from_user_id (unsigned long user_id,
|
|||
return get_user_info (NULL, user_id, credentials, NULL, NULL);
|
||||
}
|
||||
|
||||
static DBusMutex *user_info_lock = NULL;
|
||||
/**
|
||||
* Initializes the global mutex for the process's user information.
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_user_info_init_lock (void)
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (user_info);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
user_info_lock = dbus_mutex_new ();
|
||||
return user_info_lock;
|
||||
DBusString name;
|
||||
DBusString dir;
|
||||
DBusCredentials creds;
|
||||
} UserInfo;
|
||||
|
||||
static void
|
||||
shutdown_user_info (void *data)
|
||||
{
|
||||
UserInfo *u = data;
|
||||
|
||||
_dbus_string_free (&u->name);
|
||||
_dbus_string_free (&u->dir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1258,53 +1263,58 @@ _dbus_user_info_from_current_process (const DBusString **username,
|
|||
const DBusString **homedir,
|
||||
const DBusCredentials **credentials)
|
||||
{
|
||||
static DBusString name;
|
||||
static DBusString dir;
|
||||
static DBusCredentials creds;
|
||||
static dbus_bool_t initialized = FALSE;
|
||||
static UserInfo u;
|
||||
static int initialized_generation = 0;
|
||||
|
||||
if (!dbus_mutex_lock (user_info_lock))
|
||||
if (!_DBUS_LOCK (user_info))
|
||||
return FALSE;
|
||||
|
||||
if (!initialized)
|
||||
if (initialized_generation != _dbus_current_generation)
|
||||
{
|
||||
if (!_dbus_string_init (&name, _DBUS_INT_MAX))
|
||||
if (!_dbus_string_init (&u.name, _DBUS_INT_MAX))
|
||||
{
|
||||
dbus_mutex_unlock (user_info_lock);
|
||||
_DBUS_UNLOCK (user_info);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&dir, _DBUS_INT_MAX))
|
||||
if (!_dbus_string_init (&u.dir, _DBUS_INT_MAX))
|
||||
{
|
||||
_dbus_string_free (&name);
|
||||
dbus_mutex_unlock (user_info_lock);
|
||||
_dbus_string_free (&u.name);
|
||||
_DBUS_UNLOCK (user_info);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
creds.uid = -1;
|
||||
creds.gid = -1;
|
||||
creds.pid = -1;
|
||||
u.creds.uid = -1;
|
||||
u.creds.gid = -1;
|
||||
u.creds.pid = -1;
|
||||
|
||||
if (!get_user_info (NULL, getuid (),
|
||||
&creds, &dir, &name))
|
||||
&u.creds, &u.dir, &u.name))
|
||||
goto fail_init;
|
||||
|
||||
if (!_dbus_register_shutdown_func (shutdown_user_info,
|
||||
&u))
|
||||
goto fail_init;
|
||||
|
||||
initialized_generation = _dbus_current_generation;
|
||||
fail_init:
|
||||
if (initialized_generation != _dbus_current_generation)
|
||||
{
|
||||
_dbus_string_free (&name);
|
||||
_dbus_string_free (&dir);
|
||||
dbus_mutex_unlock (user_info_lock);
|
||||
_dbus_string_free (&u.name);
|
||||
_dbus_string_free (&u.dir);
|
||||
_DBUS_UNLOCK (user_info);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
if (username)
|
||||
*username = &name;
|
||||
*username = &u.name;
|
||||
if (homedir)
|
||||
*homedir = &dir;
|
||||
*homedir = &u.dir;
|
||||
if (credentials)
|
||||
*credentials = &creds;
|
||||
*credentials = &u.creds;
|
||||
|
||||
dbus_mutex_unlock (user_info_lock);
|
||||
_DBUS_UNLOCK (user_info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1594,19 +1604,7 @@ _dbus_string_append_our_uid (DBusString *str)
|
|||
}
|
||||
|
||||
|
||||
static DBusMutex *atomic_lock = NULL;
|
||||
/**
|
||||
* Initializes the global mutex for the fallback implementation
|
||||
* of atomic integers.
|
||||
*
|
||||
* @returns the mutex
|
||||
*/
|
||||
DBusMutex *
|
||||
_dbus_atomic_init_lock (void)
|
||||
{
|
||||
atomic_lock = dbus_mutex_new ();
|
||||
return atomic_lock;
|
||||
}
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
|
||||
|
||||
/**
|
||||
* Atomically increments an integer
|
||||
|
|
@ -1621,10 +1619,10 @@ _dbus_atomic_inc (dbus_atomic_t *atomic)
|
|||
{
|
||||
dbus_atomic_t res;
|
||||
|
||||
dbus_mutex_lock (atomic_lock);
|
||||
_DBUS_LOCK (atomic);
|
||||
*atomic += 1;
|
||||
res = *atomic;
|
||||
dbus_mutex_unlock (atomic_lock);
|
||||
_DBUS_UNLOCK (atomic);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1641,10 +1639,10 @@ _dbus_atomic_dec (dbus_atomic_t *atomic)
|
|||
{
|
||||
dbus_atomic_t res;
|
||||
|
||||
dbus_mutex_lock (atomic_lock);
|
||||
_DBUS_LOCK (atomic);
|
||||
*atomic -= 1;
|
||||
res = *atomic;
|
||||
dbus_mutex_unlock (atomic_lock);
|
||||
_DBUS_UNLOCK (atomic);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,5 +39,6 @@ main (int argc,
|
|||
test_data_dir = NULL;
|
||||
|
||||
dbus_internal_do_not_use_run_tests (test_data_dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,18 @@
|
|||
#include <config.h>
|
||||
#include "dbus-test.h"
|
||||
#include "dbus-sysdeps.h"
|
||||
#include "dbus-internals.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
static void
|
||||
die (const char *failure)
|
||||
{
|
||||
fprintf (stderr, "Unit test failed: %s\n", failure);
|
||||
exit (1);
|
||||
}
|
||||
#endif /* DBUS_BUILD_TESTS */
|
||||
|
||||
/**
|
||||
* An exported symbol to be run in order to execute
|
||||
|
|
@ -58,7 +61,7 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)
|
|||
printf ("%s: running string tests\n", "dbus-test");
|
||||
if (!_dbus_string_test ())
|
||||
die ("strings");
|
||||
|
||||
|
||||
printf ("%s: running data slot tests\n", "dbus-test");
|
||||
if (!_dbus_data_slot_test ())
|
||||
die ("dataslot");
|
||||
|
|
@ -96,7 +99,7 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)
|
|||
printf ("%s: running memory pool tests\n", "dbus-test");
|
||||
if (!_dbus_mem_pool_test ())
|
||||
die ("memory pools");
|
||||
|
||||
|
||||
printf ("%s: running linked list tests\n", "dbus-test");
|
||||
if (!_dbus_list_test ())
|
||||
die ("lists");
|
||||
|
|
@ -104,11 +107,21 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)
|
|||
printf ("%s: running hash table tests\n", "dbus-test");
|
||||
if (!_dbus_hash_test ())
|
||||
die ("hash tables");
|
||||
|
||||
|
||||
printf ("%s: running dict tests\n", "dbus-test");
|
||||
if (!_dbus_dict_test ())
|
||||
die ("dicts");
|
||||
|
||||
dbus_shutdown ();
|
||||
|
||||
printf ("%s: checking for memleaks\n", "dbus-test");
|
||||
if (_dbus_get_malloc_blocks_outstanding () != 0)
|
||||
{
|
||||
_dbus_warn ("%d dbus_malloc blocks were not freed\n",
|
||||
_dbus_get_malloc_blocks_outstanding ());
|
||||
die ("memleaks");
|
||||
}
|
||||
|
||||
printf ("%s: completed successfully\n", "dbus-test");
|
||||
#else
|
||||
printf ("Not compiled with unit tests, not running any\n");
|
||||
|
|
|
|||
|
|
@ -32,12 +32,21 @@ static DBusThreadFunctions thread_functions =
|
|||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
static int thread_init_generation = 0;
|
||||
|
||||
/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */
|
||||
#define _DBUS_DUMMY_MUTEX ((void*)0xABCDEF)
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
#define _DBUS_DUMMY_MUTEX_NEW ((DBusMutex*)_dbus_strdup ("FakeMutex"))
|
||||
#else
|
||||
#define _DBUS_DUMMY_MUTEX_NEW ((DBusMutex*)0xABCDEF)
|
||||
#endif
|
||||
|
||||
/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */
|
||||
#define _DBUS_DUMMY_CONDVAR ((void*)0xABCDEF2)
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
#define _DBUS_DUMMY_CONDVAR_NEW ((DBusCondVar*)_dbus_strdup ("FakeCondvar"))
|
||||
#else
|
||||
#define _DBUS_DUMMY_CONDVAR_NEW ((DBusCondVar*)0xABCDEF2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup DBusThreads Thread functions
|
||||
|
|
@ -63,7 +72,7 @@ dbus_mutex_new (void)
|
|||
if (thread_functions.mutex_new)
|
||||
return (* thread_functions.mutex_new) ();
|
||||
else
|
||||
return _DBUS_DUMMY_MUTEX;
|
||||
return _DBUS_DUMMY_MUTEX_NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -75,6 +84,11 @@ dbus_mutex_free (DBusMutex *mutex)
|
|||
{
|
||||
if (mutex && thread_functions.mutex_free)
|
||||
(* thread_functions.mutex_free) (mutex);
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
/* Free the fake mutex */
|
||||
else
|
||||
dbus_free (mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -120,7 +134,7 @@ dbus_condvar_new (void)
|
|||
if (thread_functions.condvar_new)
|
||||
return (* thread_functions.condvar_new) ();
|
||||
else
|
||||
return _DBUS_DUMMY_MUTEX;
|
||||
return _DBUS_DUMMY_CONDVAR_NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -132,6 +146,11 @@ dbus_condvar_free (DBusCondVar *cond)
|
|||
{
|
||||
if (cond && thread_functions.condvar_free)
|
||||
(* thread_functions.condvar_free) (cond);
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
else
|
||||
/* Free the fake condvar */
|
||||
dbus_free (cond);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -195,37 +214,77 @@ dbus_condvar_wake_all (DBusCondVar *cond)
|
|||
(* thread_functions.condvar_wake_all) (cond);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_global_locks (void *data)
|
||||
{
|
||||
DBusMutex ***locks = data;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (i < _DBUS_N_GLOBAL_LOCKS)
|
||||
{
|
||||
dbus_mutex_free (*(locks[i]));
|
||||
*(locks[i]) = NULL;
|
||||
++i;
|
||||
}
|
||||
|
||||
dbus_free (locks);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
init_static_locks(void)
|
||||
init_global_locks (void)
|
||||
{
|
||||
int i;
|
||||
DBusMutex ***dynamic_global_locks;
|
||||
|
||||
struct {
|
||||
DBusMutex *(*init_func)(void);
|
||||
DBusMutex *mutex;
|
||||
} static_locks[] = {
|
||||
{&_dbus_list_init_lock},
|
||||
{&_dbus_server_slots_init_lock},
|
||||
{&_dbus_connection_slots_init_lock},
|
||||
{&_dbus_atomic_init_lock},
|
||||
{&_dbus_message_handler_init_lock},
|
||||
{&_dbus_user_info_init_lock},
|
||||
{&_dbus_bus_init_lock}
|
||||
DBusMutex **global_locks[] = {
|
||||
#define LOCK_ADDR(name) (& _dbus_lock_##name)
|
||||
LOCK_ADDR (list),
|
||||
LOCK_ADDR (connection_slots),
|
||||
LOCK_ADDR (server_slots),
|
||||
LOCK_ADDR (atomic),
|
||||
LOCK_ADDR (message_handler),
|
||||
LOCK_ADDR (user_info),
|
||||
LOCK_ADDR (bus)
|
||||
#undef LOCK_ADDR
|
||||
};
|
||||
|
||||
_dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
|
||||
_DBUS_N_GLOBAL_LOCKS);
|
||||
|
||||
i = 0;
|
||||
|
||||
for (i = 0; i < _DBUS_N_ELEMENTS (static_locks); i++)
|
||||
dynamic_global_locks = dbus_new (DBusMutex**, _DBUS_N_GLOBAL_LOCKS);
|
||||
if (dynamic_global_locks == NULL)
|
||||
goto failed;
|
||||
|
||||
while (i < _DBUS_N_ELEMENTS (global_locks))
|
||||
{
|
||||
static_locks[i].mutex = (*static_locks[i].init_func)();
|
||||
|
||||
if (static_locks[i].mutex == NULL)
|
||||
{
|
||||
for (i = i - 1; i >= 0; i--)
|
||||
dbus_mutex_free (static_locks[i].mutex);
|
||||
return FALSE;
|
||||
}
|
||||
*global_locks[i] = dbus_mutex_new ();
|
||||
|
||||
if (*global_locks[i] == NULL)
|
||||
goto failed;
|
||||
|
||||
dynamic_global_locks[i] = global_locks[i];
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!_dbus_register_shutdown_func (shutdown_global_locks,
|
||||
dynamic_global_locks))
|
||||
goto failed;
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed:
|
||||
dbus_free (dynamic_global_locks);
|
||||
|
||||
for (i = i - 1; i >= 0; i--)
|
||||
{
|
||||
dbus_mutex_free (*global_locks[i]);
|
||||
*global_locks[i] = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -276,6 +335,9 @@ dbus_threads_init (const DBusThreadFunctions *functions)
|
|||
* new bits.
|
||||
*/
|
||||
_dbus_assert ((functions->mask & ~DBUS_THREAD_FUNCTIONS_ALL_MASK) == 0);
|
||||
|
||||
if (thread_init_generation != _dbus_current_generation)
|
||||
thread_functions.mask = 0; /* allow re-init in new generation */
|
||||
|
||||
if (thread_functions.mask != 0)
|
||||
{
|
||||
|
|
@ -297,8 +359,10 @@ dbus_threads_init (const DBusThreadFunctions *functions)
|
|||
|
||||
thread_functions.mask = functions->mask;
|
||||
|
||||
if (!init_static_locks ())
|
||||
if (!init_global_locks ())
|
||||
return FALSE;
|
||||
|
||||
thread_init_generation = _dbus_current_generation;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue