Diff between 07a16c4a403ae93c0ea5500315eac8a68fedb7b2 and 18f48a1b9d8229235f1a4a7b0ee4598ebaf43570

Changed Files

File Additions Deletions Status
src/gatt-dbus.c +26 -10 modified

Full Patch

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 3ded9cd..d3fd717 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -56,6 +56,7 @@ struct external_service {
 	DBusMessage *reg;
 	GDBusClient *client;
 	GSList *proxies;
+	struct btd_attribute *service;
 };
 
 struct proxy_write_data {
@@ -99,10 +100,11 @@ static void remove_service(DBusConnection *conn, void *user_data)
 {
 	struct external_service *esvc = user_data;
 
-	/* TODO: Remove from the database */
-
 	external_services = g_slist_remove(external_services, esvc);
 
+	if (esvc->service)
+		btd_gatt_remove_service(esvc->service);
+
 	/*
 	 * Do not run in the same loop, this may be a disconnect
 	 * watch call and GDBusClient should not be destroyed.
@@ -336,7 +338,7 @@ static void proxy_write_cb(struct btd_attribute *attr,
 
 }
 
-static int register_external_service(const struct external_service *esvc,
+static int register_external_service(struct external_service *esvc,
 							GDBusProxy *proxy)
 {
 	DBusMessageIter iter;
@@ -360,7 +362,8 @@ static int register_external_service(const struct external_service *esvc,
 	if (bt_string_to_uuid(&uuid, str) < 0)
 		return -EINVAL;
 
-	if (!btd_gatt_add_service(&uuid))
+	esvc->service = btd_gatt_add_service(&uuid);
+	if (!esvc->service)
 		return -EINVAL;
 
 	return 0;
@@ -481,18 +484,25 @@ static void client_ready(GDBusClient *client, void *user_data)
 	DBG("Added GATT service %s", esvc->path);
 
 	reply = dbus_message_new_method_return(esvc->reg);
-	goto reply;
+	g_dbus_send_message(conn, reply);
+
+	dbus_message_unref(esvc->reg);
+	esvc->reg = NULL;
+
+	return;
 
 fail:
 	error("Could not register external service: %s", esvc->path);
 
-	reply = btd_error_invalid_args(esvc->reg);
-	/* TODO: missing esvc/database cleanup */
+	/*
+	 * Set callback to NULL to avoid potential race condition
+	 * when calling remove_service and GDBusClient unref.
+	 */
+	g_dbus_client_set_disconnect_watch(esvc->client, NULL, NULL);
 
-reply:
-	dbus_message_unref(esvc->reg);
-	esvc->reg = NULL;
+	remove_service(conn, esvc);
 
+	reply = btd_error_invalid_args(esvc->reg);
 	g_dbus_send_message(conn, reply);
 }
 
@@ -578,6 +588,12 @@ static DBusMessage *unregister_service(DBusConnection *conn,
 	if (!strcmp(dbus_message_get_sender(msg), esvc->owner))
 		return btd_error_does_not_exist(msg);
 
+	/*
+	 * Set callback to NULL to avoid potential race condition
+	 * when calling remove_service and GDBusClient unref.
+	 */
+	g_dbus_client_set_disconnect_watch(esvc->client, NULL, NULL);
+
 	remove_service(conn, esvc);
 
 	return dbus_message_new_method_return(msg);