From d2fb01d85e290b91078637e2d3b263c8efe4afb0 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Wed, 13 Mar 2024 13:33:07 +0100 Subject: [PATCH] Fix gattlib connection release on disconnection --- common/gattlib_callback_disconnected_device.c | 3 + common/gattlib_internal_defs.h | 8 +++ dbus/gattlib.c | 63 ++++++++++++------- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/common/gattlib_callback_disconnected_device.c b/common/gattlib_callback_disconnected_device.c index ad077bb..7fb6b21 100644 --- a/common/gattlib_callback_disconnected_device.c +++ b/common/gattlib_callback_disconnected_device.c @@ -43,4 +43,7 @@ void gattlib_on_disconnected_device(gatt_connection_t* connection) { // For GATT disconnection we do not use thread to ensure the callback is synchronous. connection->on_disconnection.callback.disconnection_handler(connection, connection->on_disconnection.user_data); + + // Clean GATTLIB connection on disconnection + gattlib_connection_free(connection); } diff --git a/common/gattlib_internal_defs.h b/common/gattlib_internal_defs.h index 6e898b0..e11eb52 100644 --- a/common/gattlib_internal_defs.h +++ b/common/gattlib_internal_defs.h @@ -58,6 +58,14 @@ bool gattlib_has_valid_handler(struct gattlib_handler* handler); void gattlib_notification_device_thread(gpointer data, gpointer user_data); +/** + * Clean GATTLIB connection on disconnection + * + * This function is called by the disconnection callback to always be called on explicit + * and implicit disconnection. + */ +void gattlib_connection_free(gatt_connection_t* connection); + #if defined(WITH_PYTHON) // Callback used by Python to create arguments used by native callback void* gattlib_python_callback_args(PyObject* python_callback, PyObject* python_args); diff --git a/dbus/gattlib.c b/dbus/gattlib.c index f637eb4..aaa1d75 100644 --- a/dbus/gattlib.c +++ b/dbus/gattlib.c @@ -276,6 +276,44 @@ FREE_CONN_CONTEXT: return ret; } +/** + * Clean GATTLIB connection on disconnection + * + * This function is called by the disconnection callback to always be called on explicit + * and implicit disconnection. + */ +void gattlib_connection_free(gatt_connection_t* connection) { + gattlib_context_t* conn_context; + + g_mutex_lock(&connection->connection_mutex); + conn_context = connection->context; + + // Remove signal + if (conn_context->on_handle_device_property_change_id != 0) { + g_signal_handler_disconnect(conn_context->device, conn_context->on_handle_device_property_change_id); + conn_context->on_handle_device_property_change_id = 0; + } + + free(conn_context->device_object_path); + if (conn_context->device != NULL) { + g_object_unref(conn_context->device); + conn_context->device = NULL; + } + g_list_free_full(conn_context->dbus_objects, g_object_unref); + + disconnect_all_notifications(conn_context); + + // Note: We do not free adapter as it might still be used by other devices + + free(connection->context); + connection->context = NULL; + + g_mutex_unlock(&connection->connection_mutex); + + // And finally free the connection + free(connection); +} + int gattlib_disconnect(gatt_connection_t* connection) { gattlib_context_t* conn_context; int ret = GATTLIB_SUCCESS; @@ -297,35 +335,14 @@ int gattlib_disconnect(gatt_connection_t* connection) { GATTLIB_LOG(GATTLIB_DEBUG, "Disconnect bluetooth device %s", conn_context->device_object_path); - // Remove signal - if (conn_context->on_handle_device_property_change_id != 0) { - g_signal_handler_disconnect(conn_context->device, conn_context->on_handle_device_property_change_id); - conn_context->on_handle_device_property_change_id = 0; - } - org_bluez_device1_call_disconnect_sync(conn_context->device, NULL, &error); if (error) { GATTLIB_LOG(GATTLIB_ERROR, "Failed to disconnect DBus Bluez Device: %s", error->message); g_error_free(error); } - // Call disconnection callack. It should be called by signal but signal has been removed above - gattlib_on_disconnected_device(connection); - - free(conn_context->device_object_path); - if (conn_context->device != NULL) { - g_object_unref(conn_context->device); - conn_context->device = NULL; - } - g_list_free_full(conn_context->dbus_objects, g_object_unref); - - disconnect_all_notifications(conn_context); - - // Note: We do not free adapter as it might still be used by other devices - - free(connection->context); - connection->context = NULL; - free(connection); + //Note: Signals and memory will be removed/clean on disconnction callback + // See _gattlib_clean_on_disconnection() EXIT: g_mutex_unlock(&connection->connection_mutex);