From 09b956b8f5418917e1d586df041f90a9ed8953ef Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Tue, 24 May 2016 16:49:21 -0300 Subject: [PATCH] sol-gatt: Fix keeping pending callbacks around There was a problem that some cases of GATT pending callback were being kept around for more time than was necessary. For that to work it was also needed to pay more attention to the lifetime of the buffer passed to sol_gatt_pending_reply(). Signed-off-by: Vinicius Costa Gomes --- src/lib/comms/sol-gatt-impl-bluez.c | 42 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/lib/comms/sol-gatt-impl-bluez.c b/src/lib/comms/sol-gatt-impl-bluez.c index 7dcdffb08..3a0c4a7ef 100644 --- a/src/lib/comms/sol-gatt-impl-bluez.c +++ b/src/lib/comms/sol-gatt-impl-bluez.c @@ -145,6 +145,9 @@ sol_gatt_pending_reply(struct sol_gatt_pending *pending, int error, case PENDING_NOTIFY: r = -EINVAL; pending->buf = buf; + /* 'buf' if going to be destroyed when the notification is sent */ + buf = NULL; + SOL_NULL_CHECK_GOTO(pending->buf, done); if (attr->type == SOL_GATT_ATTR_TYPE_DESCRIPTOR) @@ -156,37 +159,40 @@ sol_gatt_pending_reply(struct sol_gatt_pending *pending, int error, attr->_priv, interface, "Value", NULL); SOL_INT_CHECK_GOTO(r, < 0, done); break; + case PENDING_REMOTE_READ: pending->read((void *)pending->user_data, true, pending->attr, buf); pending->read = NULL; + sol_ptr_vector_remove(&pending_ops, pending); destroy_pending(pending); - break; + /* Called the pending callback, nothing more to do. */ + return 0; case PENDING_REMOTE_WRITE: pending->write((void *)pending->user_data, true, pending->attr); pending->write = NULL; + sol_ptr_vector_remove(&pending_ops, pending); destroy_pending(pending); - break; - } - - if (!reply) + /* Called the pending callback, nothing more to do. */ return 0; + } - r = sd_bus_send(NULL, reply, NULL); - sd_bus_message_unref(reply); - SOL_INT_CHECK_GOTO(r, < 0, done); +done: + if (buf) + sol_buffer_fini(buf); - return 0; + if (pending->m && !reply) { + if (r) + r = sd_bus_message_new_method_errno(pending->m, &reply, r, NULL); + else + r = sd_bus_message_new_method_return(pending->m, &reply); -done: - if (r && pending->m) { - r = sd_bus_message_new_method_errno(pending->m, &reply, r, NULL); SOL_INT_CHECK(r, < 0, r); + } + if (reply) { r = sd_bus_send(NULL, reply, NULL); - sd_bus_message_unref(reply); - SOL_INT_CHECK(r, < 0, r); } @@ -290,7 +296,7 @@ attr_method(enum pending_type type, sd_bus_message *m, void *userdata, sd_bus_er sol_ptr_vector_del_last(&pending_ops); error_append: - free(pending); + destroy_pending(pending); error: if (r < 0) { @@ -827,7 +833,7 @@ prepare_update(enum pending_type type, const struct sol_gatt_attr *attr) sol_ptr_vector_del_last(&pending_ops); error_append: - free(pending); + destroy_pending(pending); return r; } @@ -920,7 +926,7 @@ sol_gatt_read_attr(struct sol_bt_conn *conn, struct sol_gatt_attr *attr, sol_ptr_vector_del_last(&pending_ops); error_append: - free(pending); + destroy_pending(pending); return r; } @@ -957,6 +963,6 @@ sol_gatt_write_attr(struct sol_bt_conn *conn, struct sol_gatt_attr *attr, sol_ptr_vector_del_last(&pending_ops); error_append: - free(pending); + destroy_pending(pending); return r; }