summaryrefslogtreecommitdiff
path: root/gdbus
diff options
context:
space:
mode:
Diffstat (limited to 'gdbus')
-rw-r--r--gdbus/watch.c79
1 files changed, 49 insertions, 30 deletions
diff --git a/gdbus/watch.c b/gdbus/watch.c
index 8ad48159..c0dcc934 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -43,11 +43,21 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
static guint listener_id = 0;
static GSList *listeners = NULL;
+struct service_data {
+ DBusConnection *conn;
+ DBusPendingCall *call;
+ char *name;
+ const char *owner;
+ guint id;
+ struct filter_callback *callback;
+};
+
struct filter_callback {
GDBusWatchFunction conn_func;
GDBusWatchFunction disc_func;
GDBusSignalFunction signal_func;
GDBusDestroyFunction destroy_func;
+ struct service_data *data;
void *user_data;
guint id;
};
@@ -302,7 +312,7 @@ static struct filter_callback *filter_data_add_callback(
{
struct filter_callback *cb = NULL;
- cb = g_new(struct filter_callback, 1);
+ cb = g_new0(struct filter_callback, 1);
cb->conn_func = connect;
cb->disc_func = disconnect;
@@ -319,6 +329,24 @@ static struct filter_callback *filter_data_add_callback(
return cb;
}
+static void service_data_free(struct service_data *data)
+{
+ struct filter_callback *callback = data->callback;
+
+ dbus_connection_unref(data->conn);
+
+ if (data->call)
+ dbus_pending_call_unref(data->call);
+
+ if (data->id)
+ g_source_remove(data->id);
+
+ g_free(data->name);
+ g_free(data);
+
+ callback->data = NULL;
+}
+
static gboolean filter_data_remove_callback(struct filter_data *data,
struct filter_callback *cb)
{
@@ -327,6 +355,13 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
data->callbacks = g_slist_remove(data->callbacks, cb);
data->processed = g_slist_remove(data->processed, cb);
+ /* Cancel pending operations */
+ if (cb->data) {
+ if (cb->data->call)
+ dbus_pending_call_cancel(cb->data->call);
+ service_data_free(cb->data);
+ }
+
if (cb->destroy_func)
cb->destroy_func(cb->user_data);
@@ -515,28 +550,14 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-struct service_data {
- DBusConnection *conn;
- char *name;
- const char *owner;
- GDBusWatchFunction conn_func;
- void *user_data;
-};
-
-static void service_data_free(struct service_data *data)
-{
- dbus_connection_unref(data->conn);
- g_free(data->name);
- g_free(data);
-}
-
static gboolean update_service(void *user_data)
{
struct service_data *data = user_data;
+ struct filter_callback *cb = data->callback;
update_name_cache(data->name, data->owner);
- if (data->conn_func)
- data->conn_func(data->conn, data->user_data);
+ if (cb->conn_func)
+ cb->conn_func(data->conn, cb->user_data);
service_data_free(data);
@@ -575,11 +596,11 @@ done:
dbus_message_unref(reply);
}
-static void check_service(DBusConnection *connection, const char *name,
- GDBusWatchFunction connect, void *user_data)
+static void check_service(DBusConnection *connection,
+ const char *name,
+ struct filter_callback *callback)
{
DBusMessage *message;
- DBusPendingCall *call;
struct service_data *data;
data = g_try_malloc0(sizeof(*data));
@@ -590,12 +611,12 @@ static void check_service(DBusConnection *connection, const char *name,
data->conn = dbus_connection_ref(connection);
data->name = g_strdup(name);
- data->conn_func = connect;
- data->user_data = user_data;
+ data->callback = callback;
+ callback->data = data;
data->owner = check_name_cache(name);
if (data->owner != NULL) {
- g_idle_add(update_service, data);
+ data->id = g_idle_add(update_service, data);
return;
}
@@ -611,21 +632,19 @@ static void check_service(DBusConnection *connection, const char *name,
DBUS_TYPE_INVALID);
if (dbus_connection_send_with_reply(connection, message,
- &call, -1) == FALSE) {
+ &data->call, -1) == FALSE) {
error("Failed to execute method call");
g_free(data);
goto done;
}
- if (call == NULL) {
+ if (data->call == NULL) {
error("D-Bus connection not available");
g_free(data);
goto done;
}
- dbus_pending_call_set_notify(call, service_reply, data, g_free);
-
- dbus_pending_call_unref(call);
+ dbus_pending_call_set_notify(data->call, service_reply, data, NULL);
done:
dbus_message_unref(message);
@@ -654,7 +673,7 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
return 0;
if (connect)
- check_service(connection, name, connect, user_data);
+ check_service(connection, name, cb);
return cb->id;
}