diff options
Diffstat (limited to 'bus')
-rw-r--r-- | bus/connection.c | 60 | ||||
-rw-r--r-- | bus/dispatch.c | 91 | ||||
-rw-r--r-- | bus/test.c | 61 |
3 files changed, 161 insertions, 51 deletions
diff --git a/bus/connection.c b/bus/connection.c index a8616683..1b59819f 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -37,6 +37,7 @@ struct BusConnections }; static int connection_data_slot = -1; +static int connection_data_slot_refcount = 0; typedef struct { @@ -51,6 +52,39 @@ typedef struct #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot)) +static dbus_bool_t +connection_data_slot_ref (void) +{ + if (connection_data_slot < 0) + { + connection_data_slot = dbus_connection_allocate_data_slot (); + + if (connection_data_slot < 0) + return FALSE; + + _dbus_assert (connection_data_slot_refcount == 0); + } + + connection_data_slot_refcount += 1; + + return TRUE; + +} + +static void +connection_data_slot_unref (void) +{ + _dbus_assert (connection_data_slot_refcount > 0); + + connection_data_slot_refcount -= 1; + + if (connection_data_slot_refcount == 0) + { + dbus_connection_free_data_slot (connection_data_slot); + connection_data_slot = -1; + } +} + void bus_connection_disconnected (DBusConnection *connection) { @@ -209,6 +243,7 @@ free_connection_data (void *data) if (d->oom_preallocated) dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated); + if (d->oom_message) dbus_message_unref (d->oom_message); @@ -222,17 +257,15 @@ bus_connections_new (BusContext *context) { BusConnections *connections; - if (connection_data_slot < 0) - { - connection_data_slot = dbus_connection_allocate_data_slot (); - - if (connection_data_slot < 0) - return NULL; - } + if (!connection_data_slot_ref ()) + return NULL; connections = dbus_new0 (BusConnections, 1); if (connections == NULL) - return NULL; + { + connection_data_slot_unref (); + return NULL; + } connections->refcount = 1; connections->context = context; @@ -268,7 +301,9 @@ bus_connections_unref (BusConnections *connections) _dbus_list_clear (&connections->list); - dbus_free (connections); + dbus_free (connections); + + connection_data_slot_unref (); } } @@ -286,6 +321,8 @@ bus_connections_setup_connection (BusConnections *connections, d->connections = connections; d->connection = connection; + + _dbus_assert (connection_data_slot >= 0); if (!dbus_connection_set_data (connection, connection_data_slot, @@ -329,6 +366,11 @@ bus_connections_setup_connection (BusConnections *connections, out: if (!retval) { + if (!dbus_connection_set_data (connection, + connection_data_slot, + NULL, NULL)) + _dbus_assert_not_reached ("failed to set connection data to null"); + if (!dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, connection, diff --git a/bus/dispatch.c b/bus/dispatch.c index ffb7bd9f..5365a11d 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -33,7 +33,7 @@ #include <dbus/dbus-internals.h> #include <string.h> -static int message_handler_slot; +static int message_handler_slot = -1; static int message_handler_slot_refcount; typedef struct @@ -157,7 +157,7 @@ bus_dispatch (DBusConnection *connection, transaction = NULL; dbus_error_init (&error); - + context = bus_connection_get_context (connection); _dbus_assert (context != NULL); @@ -334,10 +334,15 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, static dbus_bool_t message_handler_slot_ref (void) { - message_handler_slot = dbus_connection_allocate_data_slot (); - if (message_handler_slot < 0) - return FALSE; + { + message_handler_slot = dbus_connection_allocate_data_slot (); + + if (message_handler_slot < 0) + return FALSE; + + _dbus_assert (message_handler_slot_refcount == 0); + } message_handler_slot_refcount += 1; @@ -348,7 +353,9 @@ static void message_handler_slot_unref (void) { _dbus_assert (message_handler_slot_refcount > 0); + message_handler_slot_refcount -= 1; + if (message_handler_slot_refcount == 0) { dbus_connection_free_data_slot (message_handler_slot); @@ -356,6 +363,18 @@ message_handler_slot_unref (void) } } +static void +free_message_handler (void *data) +{ + DBusMessageHandler *handler = data; + + _dbus_assert (message_handler_slot >= 0); + _dbus_assert (message_handler_slot_refcount > 0); + + dbus_message_handler_unref (handler); + message_handler_slot_unref (); +} + dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection) { @@ -369,7 +388,7 @@ bus_dispatch_add_connection (DBusConnection *connection) { message_handler_slot_unref (); return FALSE; - } + } if (!dbus_connection_add_filter (connection, handler)) { @@ -379,12 +398,14 @@ bus_dispatch_add_connection (DBusConnection *connection) return FALSE; } + _dbus_assert (message_handler_slot >= 0); + _dbus_assert (message_handler_slot_refcount > 0); + if (!dbus_connection_set_data (connection, message_handler_slot, handler, - (DBusFreeFunction)dbus_message_handler_unref)) + free_message_handler)) { - dbus_connection_remove_filter (connection, handler); dbus_message_handler_unref (handler); message_handler_slot_unref (); @@ -403,8 +424,6 @@ bus_dispatch_remove_connection (DBusConnection *connection) dbus_connection_set_data (connection, message_handler_slot, NULL, NULL); - - message_handler_slot_unref (); } #ifdef DBUS_BUILD_TESTS @@ -551,6 +570,23 @@ kill_client_connection (BusContext *context, _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client"); } +static void +kill_client_connection_unchecked (DBusConnection *connection) +{ + /* This kills the connection without expecting it to affect + * the rest of the bus. + */ + _dbus_verbose ("Unchecked kill of connection %p\n", connection); + + dbus_connection_ref (connection); + dbus_connection_disconnect (connection); + /* dispatching disconnect handler will unref once */ + if (bus_connection_dispatch_one_message (connection)) + _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register"); + dbus_connection_unref (connection); + _dbus_assert (!bus_test_client_listed (connection)); +} + typedef struct { dbus_bool_t failed; @@ -691,7 +727,10 @@ check_hello_message (BusContext *context, return TRUE; if (!dbus_connection_send (connection, message, &serial)) - return TRUE; + { + dbus_message_unref (message); + return TRUE; + } dbus_message_unref (message); message = NULL; @@ -870,15 +909,7 @@ check_hello_connection (BusContext *context) /* We didn't successfully register, so we can't * do the usual kill_client_connection() checks */ - dbus_connection_ref (connection); - dbus_connection_disconnect (connection); - /* dispatching disconnect handler will unref once */ - if (bus_connection_dispatch_one_message (connection)) - _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register"); - dbus_connection_unref (connection); - _dbus_assert (!bus_test_client_listed (connection)); - - return TRUE; + kill_client_connection_unchecked (connection); } else { @@ -928,6 +959,9 @@ check1_try_iterations (BusContext *context, } _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); + + _dbus_verbose ("=================\n%s: all iterations passed\n=================\n", + description); } dbus_bool_t @@ -981,20 +1015,11 @@ bus_dispatch_test (const DBusString *test_data_dir) check1_try_iterations (context, "create_and_hello", check_hello_connection); - dbus_connection_disconnect (foo); - if (bus_connection_dispatch_one_message (foo)) - _dbus_assert_not_reached ("extra message in queue"); - _dbus_assert (!bus_test_client_listed (foo)); - - dbus_connection_disconnect (bar); - if (bus_connection_dispatch_one_message (bar)) - _dbus_assert_not_reached ("extra message in queue"); - _dbus_assert (!bus_test_client_listed (bar)); + _dbus_verbose ("Disconnecting foo, bar, and baz\n"); - dbus_connection_disconnect (baz); - if (bus_connection_dispatch_one_message (baz)) - _dbus_assert_not_reached ("extra message in queue"); - _dbus_assert (!bus_test_client_listed (baz)); + kill_client_connection_unchecked (foo); + kill_client_connection_unchecked (bar); + kill_client_connection_unchecked (baz); bus_context_unref (context); @@ -112,6 +112,49 @@ client_disconnect_handler (DBusMessageHandler *handler, } static int handler_slot = -1; +static int handler_slot_refcount = 0; + +static dbus_bool_t +handler_slot_ref (void) +{ + if (handler_slot < 0) + { + handler_slot = dbus_connection_allocate_data_slot (); + + if (handler_slot < 0) + return FALSE; + + _dbus_assert (handler_slot_refcount == 0); + } + + handler_slot_refcount += 1; + + return TRUE; + +} + +static void +handler_slot_unref (void) +{ + _dbus_assert (handler_slot_refcount > 0); + + handler_slot_refcount -= 1; + + if (handler_slot_refcount == 0) + { + dbus_connection_free_data_slot (handler_slot); + handler_slot = -1; + } +} + +static void +free_handler (void *data) +{ + DBusMessageHandler *handler = data; + + dbus_message_handler_unref (handler); + handler_slot_unref (); +} dbus_bool_t bus_setup_debug_client (DBusConnection *connection) @@ -119,11 +162,6 @@ bus_setup_debug_client (DBusConnection *connection) DBusMessageHandler *disconnect_handler; const char *to_handle[] = { DBUS_MESSAGE_LOCAL_DISCONNECT }; dbus_bool_t retval; - - if (handler_slot < 0) - handler_slot = dbus_connection_allocate_data_slot (); - if (handler_slot < 0) - return FALSE; disconnect_handler = dbus_message_handler_new (client_disconnect_handler, NULL, NULL); @@ -160,12 +198,17 @@ bus_setup_debug_client (DBusConnection *connection) if (!_dbus_list_append (&clients, connection)) goto out; - /* Set up handler to be destroyed */ + if (!handler_slot_ref ()) + goto out; + + /* Set up handler to be destroyed */ if (!dbus_connection_set_data (connection, handler_slot, disconnect_handler, - (DBusFreeFunction) - dbus_message_handler_unref)) - goto out; + free_handler)) + { + handler_slot_unref (); + goto out; + } retval = TRUE; |