diff options
Diffstat (limited to 'gdbus')
-rw-r--r-- | gdbus/client.c | 14 | ||||
-rw-r--r-- | gdbus/mainloop.c | 10 | ||||
-rw-r--r-- | gdbus/object.c | 8 | ||||
-rw-r--r-- | gdbus/watch.c | 15 |
4 files changed, 31 insertions, 16 deletions
diff --git a/gdbus/client.c b/gdbus/client.c index 3bf883ac..eb68a0f8 100644 --- a/gdbus/client.c +++ b/gdbus/client.c @@ -51,6 +51,7 @@ struct GDBusClient { GDBusWatchFunction connect_func; void *connect_data; GDBusWatchFunction disconn_func; + gboolean connected; void *disconn_data; GDBusMessageFunction signal_func; void *signal_data; @@ -1146,6 +1147,8 @@ static void service_connect(DBusConnection *conn, void *user_data) get_managed_objects(client); + client->connected = TRUE; + g_dbus_client_unref(client); } @@ -1156,8 +1159,10 @@ static void service_disconnect(DBusConnection *conn, void *user_data) g_list_free_full(client->proxy_list, proxy_free); client->proxy_list = NULL; - if (client->disconn_func) + if (client->disconn_func) { client->disconn_func(conn, client->disconn_data); + client->connected = FALSE; + } } static DBusHandlerResult message_filter(DBusConnection *connection, @@ -1210,6 +1215,7 @@ GDBusClient *g_dbus_client_new(DBusConnection *connection, client->dbus_conn = dbus_connection_ref(connection); client->service_name = g_strdup(service); client->base_path = g_strdup(path); + client->connected = FALSE; client->match_rules = g_ptr_array_sized_new(1); g_ptr_array_set_free_func(client->match_rules, g_free); @@ -1284,7 +1290,11 @@ void g_dbus_client_unref(GDBusClient *client) g_list_free_full(client->proxy_list, proxy_free); - if (client->disconn_func) + /* + * Don't call disconn_func twice if disconnection + * was previously reported. + */ + if (client->disconn_func && client->connected) client->disconn_func(client->dbus_conn, client->disconn_data); g_dbus_remove_watch(client->dbus_conn, client->watch); diff --git a/gdbus/mainloop.c b/gdbus/mainloop.c index 435fb93b..3e88eac8 100644 --- a/gdbus/mainloop.c +++ b/gdbus/mainloop.c @@ -88,16 +88,22 @@ static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) struct watch_info *info = data; unsigned int flags = 0; DBusDispatchStatus status; + DBusConnection *conn; if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; + /* Protect connection from being destroyed by dbus_watch_handle */ + conn = dbus_connection_ref(info->conn); + dbus_watch_handle(info->watch, flags); - status = dbus_connection_get_dispatch_status(info->conn); - queue_dispatch(info->conn, status); + status = dbus_connection_get_dispatch_status(conn); + queue_dispatch(conn, status); + + dbus_connection_unref(conn); return TRUE; } diff --git a/gdbus/object.c b/gdbus/object.c index 13cf9a95..4d5a64cb 100644 --- a/gdbus/object.c +++ b/gdbus/object.c @@ -1088,7 +1088,6 @@ static const GDBusMethodTable introspect_methods[] = { static void append_interfaces(struct generic_data *data, DBusMessageIter *iter) { DBusMessageIter array; - GSList *l; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING @@ -1100,12 +1099,7 @@ static void append_interfaces(struct generic_data *data, DBusMessageIter *iter) DBUS_DICT_ENTRY_END_CHAR_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array); - for (l = data->interfaces; l != NULL; l = l->next) { - if (g_slist_find(data->added, l->data)) - continue; - - append_interface(l->data, &array); - } + g_slist_foreach(data->interfaces, append_interface, &array); dbus_message_iter_close_container(iter, &array); } diff --git a/gdbus/watch.c b/gdbus/watch.c index 0f99f4f1..0d0054c1 100644 --- a/gdbus/watch.c +++ b/gdbus/watch.c @@ -362,6 +362,7 @@ static void service_data_free(struct service_data *data) callback->data = NULL; } +/* Returns TRUE if data is freed */ static gboolean filter_data_remove_callback(struct filter_data *data, struct filter_callback *cb) { @@ -383,7 +384,7 @@ static gboolean filter_data_remove_callback(struct filter_data *data, /* Don't remove the filter if other callbacks exist or data is lock * processing callbacks */ if (data->callbacks || data->lock) - return TRUE; + return FALSE; if (data->registered && !remove_match(data)) return FALSE; @@ -405,7 +406,9 @@ static DBusHandlerResult signal_filter(DBusConnection *connection, if (cb->signal_func && !cb->signal_func(connection, message, cb->user_data)) { - filter_data_remove_callback(data, cb); + if (filter_data_remove_callback(data, cb)) + break; + continue; } @@ -489,7 +492,9 @@ static DBusHandlerResult service_filter(DBusConnection *connection, /* Only auto remove if it is a bus name watch */ if (data->argument[0] == ':' && (cb->conn_func == NULL || cb->disc_func == NULL)) { - filter_data_remove_callback(data, cb); + if (filter_data_remove_callback(data, cb)) + break; + continue; } @@ -590,7 +595,6 @@ static gboolean update_service(void *user_data) struct filter_callback *cb = data->callback; DBusConnection *conn; - update_name_cache(data->name, data->owner); conn = dbus_connection_ref(data->conn); service_data_free(data); @@ -699,7 +703,8 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name, if (name == NULL) return 0; - data = filter_data_get(connection, service_filter, NULL, NULL, + data = filter_data_get(connection, service_filter, + DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameOwnerChanged", name); if (data == NULL) |