diff options
Diffstat (limited to 'bus/connection.c')
-rw-r--r-- | bus/connection.c | 113 |
1 files changed, 107 insertions, 6 deletions
diff --git a/bus/connection.c b/bus/connection.c index 80a9ae7a..2cfbeb27 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -139,6 +139,8 @@ bus_connection_disconnected (DBusConnection *connection) if (!bus_service_remove_owner (service, connection, transaction, &error)) { + _DBUS_ASSERT_ERROR_IS_SET (&error); + if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) { dbus_error_free (&error); @@ -147,7 +149,11 @@ bus_connection_disconnected (DBusConnection *connection) goto retry; } else - _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason"); + { + _dbus_verbose ("Failed to remove service owner: %s %s\n", + error.name, error.message); + _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason"); + } } bus_transaction_execute_and_free (transaction); @@ -746,19 +752,31 @@ bus_connection_send_oom_error (DBusConnection *connection, d->oom_preallocated = NULL; } -dbus_bool_t -bus_connection_add_owned_service (DBusConnection *connection, - BusService *service) +void +bus_connection_add_owned_service_link (DBusConnection *connection, + DBusList *link) { BusConnectionData *d; d = BUS_CONNECTION_DATA (connection); _dbus_assert (d != NULL); - if (!_dbus_list_append (&d->services_owned, - service)) + _dbus_list_append_link (&d->services_owned, link); +} + +dbus_bool_t +bus_connection_add_owned_service (DBusConnection *connection, + BusService *service) +{ + DBusList *link; + + link = _dbus_list_alloc_link (service); + + if (link == NULL) return FALSE; + bus_connection_add_owned_service_link (connection, link); + return TRUE; } @@ -805,6 +823,13 @@ bus_connection_get_name (DBusConnection *connection) return d->name; } +/** + * Transactions + * + * Note that this is fairly fragile; in particular, don't try to use + * one transaction across any main loop iterations. + */ + typedef struct { BusTransaction *transaction; @@ -812,10 +837,18 @@ typedef struct DBusPreallocatedSend *preallocated; } MessageToSend; +typedef struct +{ + BusTransactionCancelFunction cancel_function; + DBusFreeFunction free_data_function; + void *data; +} CancelHook; + struct BusTransaction { DBusList *connections; BusContext *context; + DBusList *cancel_hooks; }; static void @@ -831,6 +864,39 @@ message_to_send_free (DBusConnection *connection, dbus_free (to_send); } +static void +cancel_hook_cancel (void *element, + void *data) +{ + CancelHook *ch = element; + + _dbus_verbose ("Running transaction cancel hook\n"); + + if (ch->cancel_function) + (* ch->cancel_function) (ch->data); +} + +static void +cancel_hook_free (void *element, + void *data) +{ + CancelHook *ch = element; + + if (ch->free_data_function) + (* ch->free_data_function) (ch->data); + + dbus_free (ch); +} + +static void +free_cancel_hooks (BusTransaction *transaction) +{ + _dbus_list_foreach (&transaction->cancel_hooks, + cancel_hook_free, NULL); + + _dbus_list_clear (&transaction->cancel_hooks); +} + BusTransaction* bus_transaction_new (BusContext *context) { @@ -980,6 +1046,11 @@ bus_transaction_cancel_and_free (BusTransaction *transaction) _dbus_assert (transaction->connections == NULL); + _dbus_list_foreach (&transaction->cancel_hooks, + cancel_hook_cancel, NULL); + + free_cancel_hooks (transaction); + dbus_free (transaction); } @@ -1036,6 +1107,8 @@ bus_transaction_execute_and_free (BusTransaction *transaction) _dbus_assert (transaction->connections == NULL); + free_cancel_hooks (transaction); + dbus_free (transaction); } @@ -1090,3 +1163,31 @@ bus_transaction_send_error_reply (BusTransaction *transaction, return TRUE; } + +dbus_bool_t +bus_transaction_add_cancel_hook (BusTransaction *transaction, + BusTransactionCancelFunction cancel_function, + void *data, + DBusFreeFunction free_data_function) +{ + CancelHook *ch; + + ch = dbus_new (CancelHook, 1); + if (ch == NULL) + return FALSE; + + ch->cancel_function = cancel_function; + ch->data = data; + ch->free_data_function = free_data_function; + + /* It's important that the hooks get run in reverse order that they + * were added + */ + if (!_dbus_list_prepend (&transaction->cancel_hooks, ch)) + { + dbus_free (ch); + return FALSE; + } + + return TRUE; +} |