if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
goto oom;
- _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
- if (!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
+ if (!_dbus_list_get_stats (&in_use, &in_free_list, &allocated) ||
+ !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolCachedBytes",
in_free_list) ||
!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolAllocatedBytes",
if (bd->is_well_known)
{
int i;
- _DBUS_LOCK (bus);
+
+ if (!_DBUS_LOCK (bus))
+ _dbus_assert_not_reached ("global locks should have been initialized "
+ "when we attached bus data");
+
/* We may be stored in more than one slot */
/* This should now be impossible - these slots are supposed to
* be cleared on disconnect, so should not need to be cleared on
_dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection)
{
int i;
-
- _DBUS_LOCK (bus);
+
+ if (!_DBUS_LOCK (bus))
+ {
+ /* If it was in bus_connections, we would have initialized global locks
+ * when we added it. So, it can't be. */
+ return;
+ }
/* We are expecting to have the connection saved in only one of these
* slots, but someone could in a pathological case set system and session
connection = NULL;
- _DBUS_LOCK (bus);
+ if (!_DBUS_LOCK (bus))
+ {
+ _DBUS_SET_OOM (error);
+ /* do not "goto out", that would try to unlock */
+ return NULL;
+ }
if (!init_connections_unlocked ())
{
*/
dbus_connection_set_exit_on_disconnect (connection,
TRUE);
-
- _DBUS_LOCK (bus_datas);
+
+ if (!_DBUS_LOCK (bus_datas))
+ _dbus_assert_not_reached ("global locks were initialized already");
+
bd = ensure_bus_data (connection);
_dbus_assert (bd != NULL); /* it should have been created on
register, so OOM not possible */
message = NULL;
reply = NULL;
- _DBUS_LOCK (bus_datas);
+ if (!_DBUS_LOCK (bus_datas))
+ {
+ _DBUS_SET_OOM (error);
+ /* do not "goto out", that would try to unlock */
+ return FALSE;
+ }
bd = ensure_bus_data (connection);
if (bd == NULL)
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (unique_name != NULL, FALSE);
- _DBUS_LOCK (bus_datas);
-
+ if (!_DBUS_LOCK (bus_datas))
+ {
+ /* do not "goto out", that would try to unlock */
+ return FALSE;
+ }
+
bd = ensure_bus_data (connection);
if (bd == NULL)
goto out;
_dbus_return_val_if_fail (connection != NULL, NULL);
- _DBUS_LOCK (bus_datas);
-
+ if (!_DBUS_LOCK (bus_datas))
+ {
+ /* We'd have initialized locks when we gave it its unique name, if it
+ * had one. Don't "goto out", that would try to unlock. */
+ return NULL;
+ }
+
bd = ensure_bus_data (connection);
if (bd == NULL)
goto out;
shared_connections_shutdown (void *data)
{
int n_entries;
-
- _DBUS_LOCK (shared_connections);
-
+
+ if (!_DBUS_LOCK (shared_connections))
+ {
+ /* We'd have initialized locks before adding anything, so there
+ * can't be anything there. */
+ return;
+ }
+
/* This is a little bit unpleasant... better ideas? */
while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
{
_DBUS_UNLOCK (shared_connections);
close_connection_on_shutdown (connection);
- _DBUS_LOCK (shared_connections);
+ if (!_DBUS_LOCK (shared_connections))
+ _dbus_assert_not_reached ("global locks were already initialized");
/* The connection should now be dead and not in our hash ... */
_dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
{
_DBUS_UNLOCK (shared_connections);
close_connection_on_shutdown (connection);
- _DBUS_LOCK (shared_connections);
+ if (!_DBUS_LOCK (shared_connections))
+ _dbus_assert_not_reached ("global locks were already initialized");
connection = _dbus_list_pop_first (&shared_connections_no_guid);
}
}
_dbus_verbose ("checking for existing connection\n");
*result = NULL;
-
- _DBUS_LOCK (shared_connections);
+
+ if (!_DBUS_LOCK (shared_connections))
+ {
+ /* If it was shared, we'd have initialized global locks when we put
+ * it in shared_connections. */
+ return FALSE;
+ }
if (shared_connections == NULL)
{
if (guid == NULL)
{
- _DBUS_LOCK (shared_connections);
+ if (!_DBUS_LOCK (shared_connections))
+ return FALSE;
if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
{
dbus_free (guid_key);
return FALSE;
}
-
- _DBUS_LOCK (shared_connections);
+
+ if (!_DBUS_LOCK (shared_connections))
+ {
+ dbus_free (guid_in_connection);
+ dbus_free (guid_key);
+ return FALSE;
+ }
+
_dbus_assert (shared_connections != NULL);
if (!_dbus_hash_table_insert_string (shared_connections,
if (!connection->shareable)
return;
-
- _DBUS_LOCK (shared_connections);
-
+
+ if (!_DBUS_LOCK (shared_connections))
+ {
+ /* If it was shared, we'd have initialized global locks when we put
+ * it in the table; so it can't be there. */
+ return;
+ }
+
if (connection->server_guid != NULL)
{
_dbus_verbose ("dropping connection to %s out of the shared table\n",
{
dbus_int32_t slot;
- _dbus_lock (allocator->lock);
+ if (!_dbus_lock (allocator->lock))
+ return FALSE;
if (*slot_id_p >= 0)
{
_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
dbus_int32_t *slot_id_p)
{
- _dbus_lock (allocator->lock);
-
+ if (!_dbus_lock (allocator->lock))
+ _dbus_assert_not_reached ("we should have initialized global locks "
+ "before we allocated this slot");
+
_dbus_assert (*slot_id_p < allocator->n_allocated_slots);
_dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
_dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);
* be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
* are disabled, since then the asserts are empty.
*/
- _dbus_lock (allocator->lock);
+ if (!_dbus_lock (allocator->lock))
+ _dbus_assert_not_reached ("we should have initialized global locks "
+ "before we allocated this slot");
+
_dbus_assert (slot < allocator->n_allocated_slots);
_dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
_dbus_unlock (allocator->lock);
* be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
* are disabled, since then the asserts are empty.
*/
- _dbus_lock (allocator->lock);
+ if (!_dbus_lock (allocator->lock))
+ _dbus_assert_not_reached ("we should have initialized global locks "
+ "before we allocated this slot");
+
_dbus_assert (slot >= 0);
_dbus_assert (slot < allocator->n_allocated_slots);
_dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
/**
* @def _DBUS_LOCK
*
- * Locks a global lock
+ * Locks a global lock, initializing it first if necessary.
+ *
+ * @returns #FALSE if not enough memory
*/
/**
{
dbus_bool_t ok;
- _DBUS_LOCK (machine_uuid);
+ if (!_DBUS_LOCK (machine_uuid))
+ return FALSE;
+
if (machine_uuid_initialized_generation != _dbus_current_generation)
{
DBusError error = DBUS_ERROR_INIT;
_DBUS_N_GLOBAL_LOCKS
} DBusGlobalLock;
-void _dbus_lock (DBusGlobalLock lock);
-void _dbus_unlock (DBusGlobalLock lock);
+dbus_bool_t _dbus_lock (DBusGlobalLock lock) _DBUS_GNUC_WARN_UNUSED_RESULT;
+void _dbus_unlock (DBusGlobalLock lock);
#define _DBUS_LOCK_NAME(name) _DBUS_LOCK_##name
#define _DBUS_LOCK(name) _dbus_lock (_DBUS_LOCK_##name)
{
DBusList *link;
- _DBUS_LOCK (list);
+ if (!_DBUS_LOCK (list))
+ return FALSE;
if (list_pool == NULL)
{
static void
free_link (DBusList *link)
{
- _DBUS_LOCK (list);
+ if (!_DBUS_LOCK (list))
+ _dbus_assert_not_reached ("we should have initialized global locks "
+ "before we allocated a linked-list link");
+
if (_dbus_mem_pool_dealloc (list_pool, link))
{
_dbus_mem_pool_free (list_pool);
dbus_uint32_t *in_free_list_p,
dbus_uint32_t *allocated_p)
{
- _DBUS_LOCK (list);
+ if (!_DBUS_LOCK (list))
+ {
+ *in_use_p = 0;
+ *in_free_list_p = 0;
+ *allocated_p = 0;
+ return;
+ }
+
_dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
_DBUS_UNLOCK (list);
}
{
dbus_bool_t ok;
- _DBUS_LOCK (shutdown_funcs);
+ if (!_DBUS_LOCK (shutdown_funcs))
+ return FALSE;
+
ok = _dbus_register_shutdown_func_unlocked (func, data);
_DBUS_UNLOCK (shutdown_funcs);
return ok;
{
int i;
- _DBUS_LOCK (message_cache);
+ if (!_DBUS_LOCK (message_cache))
+ _dbus_assert_not_reached ("we would have initialized global locks "
+ "before registering a shutdown function");
i = 0;
while (i < MAX_MESSAGE_CACHE_SIZE)
message = NULL;
- _DBUS_LOCK (message_cache);
+ if (!_DBUS_LOCK (message_cache))
+ {
+ /* we'd have initialized global locks before caching anything,
+ * so there can't be anything in the cache */
+ return NULL;
+ }
_dbus_assert (message_cache_count >= 0);
was_cached = FALSE;
- _DBUS_LOCK (message_cache);
+ if (!_DBUS_LOCK (message_cache))
+ {
+ /* The only way to get a non-null message goes through
+ * dbus_message_get_cached() which takes the lock. */
+ _dbus_assert_not_reached ("we would have initialized global locks "
+ "the first time we constructed a message");
+ }
if (!message_cache_shutdown_registered)
{
_dbus_list_clear (&uninitialized_condvar_list);
}
+/* init_global_locks() must be called first. */
static dbus_bool_t
init_uninitialized_locks (void)
{
DBusList *link;
+ dbus_bool_t ok;
_dbus_assert (thread_init_generation != _dbus_current_generation);
_dbus_list_clear (&uninitialized_cmutex_list);
_dbus_list_clear (&uninitialized_condvar_list);
- if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks,
- NULL))
+ /* This assumes that init_global_locks() has already been called. */
+ _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
+ ok = _dbus_register_shutdown_func_unlocked (shutdown_uninitialized_locks, NULL);
+ _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
+
+ if (!ok)
goto fail_condvar;
return TRUE;
goto failed;
}
- _dbus_lock (_DBUS_LOCK_NAME (shutdown_funcs));
+ _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL);
- _dbus_unlock (_DBUS_LOCK_NAME (shutdown_funcs));
+ _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
if (!ok)
goto failed;
return FALSE;
}
-void
+dbus_bool_t
_dbus_lock (DBusGlobalLock lock)
{
_dbus_assert (lock >= 0);
_dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
- if (thread_init_generation == _dbus_current_generation)
- _dbus_platform_rmutex_lock (global_locks[lock]);
+ if (thread_init_generation != _dbus_current_generation &&
+ !dbus_threads_init_default ())
+ return FALSE;
+
+ _dbus_platform_rmutex_lock (global_locks[lock]);
+ return TRUE;
}
void
_dbus_assert (lock >= 0);
_dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
- if (thread_init_generation == _dbus_current_generation)
- _dbus_platform_rmutex_unlock (global_locks[lock]);
+ _dbus_platform_rmutex_unlock (global_locks[lock]);
}
/** @} */ /* end of internals */
}
if (!_dbus_threads_init_platform_specific() ||
+ /* init_global_locks() must be called before init_uninitialized_locks. */
!init_global_locks () ||
!init_uninitialized_locks ())
{
#endif /* HAVE_CONSOLE_OWNER_FILE */
- _dbus_user_database_lock_system ();
+ if (!_dbus_user_database_lock_system ())
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
db = _dbus_user_database_get_system ();
if (db == NULL)
{
DBusUserDatabase *db;
const DBusGroupInfo *info;
- _dbus_user_database_lock_system ();
+
+ /* FIXME: this can't distinguish ENOMEM from other errors */
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
db = _dbus_user_database_get_system ();
if (db == NULL)
{
DBusUserDatabase *db;
const DBusUserInfo *info;
- _dbus_user_database_lock_system ();
+
+ /* FIXME: this can't distinguish ENOMEM from other errors */
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
db = _dbus_user_database_get_system ();
if (db == NULL)
*group_ids = NULL;
*n_group_ids = 0;
- _dbus_user_database_lock_system ();
+ /* FIXME: this can't distinguish ENOMEM from other errors */
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
db = _dbus_user_database_get_system ();
if (db == NULL)
/**
* Locks global system user database.
*/
-void
+dbus_bool_t
_dbus_user_database_lock_system (void)
{
- _DBUS_LOCK (system_users);
- database_locked = TRUE;
+ if (_DBUS_LOCK (system_users))
+ {
+ database_locked = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
/**
void
_dbus_user_database_flush_system (void)
{
- _dbus_user_database_lock_system ();
-
+ if (!_dbus_user_database_lock_system ())
+ {
+ /* nothing to flush */
+ return;
+ }
+
if (system_db != NULL)
_dbus_user_database_flush (system_db);
dbus_bool_t
_dbus_username_from_current_process (const DBusString **username)
{
- _dbus_user_database_lock_system ();
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
+
if (!init_system_db ())
{
_dbus_user_database_unlock_system ();
dbus_bool_t
_dbus_homedir_from_current_process (const DBusString **homedir)
{
- _dbus_user_database_lock_system ();
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
+
if (!init_system_db ())
{
_dbus_user_database_unlock_system ();
{
DBusUserDatabase *db;
const DBusUserInfo *info;
- _dbus_user_database_lock_system ();
+
+ /* FIXME: this can't distinguish ENOMEM from other errors */
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
db = _dbus_user_database_get_system ();
if (db == NULL)
{
DBusUserDatabase *db;
const DBusUserInfo *info;
- _dbus_user_database_lock_system ();
+
+ /* FIXME: this can't distinguish ENOMEM from other errors */
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
db = _dbus_user_database_get_system ();
if (db == NULL)
DBusUserDatabase *db;
const DBusUserInfo *info;
- _dbus_user_database_lock_system ();
+ /* FIXME: this can't distinguish ENOMEM from other errors */
+ if (!_dbus_user_database_lock_system ())
+ return FALSE;
db = _dbus_user_database_get_system ();
if (db == NULL)
#endif /* DBUS_USERDB_INCLUDES_PRIVATE */
DBusUserDatabase* _dbus_user_database_get_system (void);
-void _dbus_user_database_lock_system (void);
+dbus_bool_t _dbus_user_database_lock_system (void) _DBUS_GNUC_WARN_UNUSED_RESULT;
void _dbus_user_database_unlock_system (void);
void _dbus_user_database_flush_system (void);
&dispatch_cond1,
&io_path_cond1);
- check_mutex_lock (mutex1, mutex2, FALSE);
- check_mutex_lock (dispatch_mutex1, dispatch_mutex2, FALSE);
- check_mutex_lock (io_path_mutex1, io_path_mutex2, FALSE);
- check_condvar_lock (dispatch_cond1, dispatch_cond2, FALSE);
- check_condvar_lock (io_path_cond1, io_path_cond2, FALSE);
+ /* Since 1.7 it is no longer the case that mutex1 != mutex2, because
+ * initializing global locks automatically initializes locks
+ * in general. However, it is true that the mutex is not the dummy
+ * implementation, which is what we really wanted to check here. */
+ _dbus_assert (mutex1 != (DBusMutex *) 0xABCDEF);
+ _dbus_assert (dispatch_mutex1 != (DBusMutex *) 0xABCDEF);
+ _dbus_assert (dispatch_cond1 != (DBusCondVar *) 0xABCDEF2);
+ _dbus_assert (io_path_mutex1 != (DBusMutex *) 0xABCDEF);
+ _dbus_assert (io_path_cond1 != (DBusCondVar *) 0xABCDEF2);
_run_iteration (conn);
_dbus_connection_test_get_locks (conn, &mutex2,