From d5600f9918a0d2b6e9c5ea117574c2b0f5520926 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 30 Oct 2014 17:34:12 +0200 Subject: [PATCH] shared/att: Fix another memory leak In case of bt_att_cancel_all before resetting destroy callback to NULL it needs to be called so the requestor can properly free the resources: 104 (40 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 47 of 55 at 0x4C291D4: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) by 0x408359: bt_gatt_exchange_mtu (gatt-helpers.c:479) by 0x405345: bt_gatt_client_new (gatt-client.c:1196) by 0x401A4B: test_client (test-gatt.c:198) by 0x4E9E5E0: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2) by 0x4E9E7A5: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2) by 0x4E9E7A5: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2) by 0x4E9E7A5: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2) by 0x4E9EB1A: g_test_run_suite (in /usr/lib64/libglib-2.0.so.0.3800.2) by 0x40162E: main (test-gatt.c:265) --- src/shared/att.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/shared/att.c b/src/shared/att.c index 715c96890..6adde2209 100644 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -194,6 +194,16 @@ static void destroy_att_send_op(void *data) free(op); } +static void cancel_att_send_op(struct att_send_op *op) +{ + if (op->destroy) + op->destroy(op->user_data); + + op->user_data = NULL; + op->callback = NULL; + op->destroy = NULL; +} + struct att_notify { unsigned int id; uint16_t opcode; @@ -1036,15 +1046,13 @@ bool bt_att_cancel(struct bt_att *att, unsigned int id) if (att->pending_req && att->pending_req->id == id) { /* Don't cancel the pending request; remove it's handlers */ - att->pending_req->callback = NULL; - att->pending_req->destroy = NULL; + cancel_att_send_op(att->pending_req); return true; } if (att->pending_ind && att->pending_ind->id == id) { /* Don't cancel the pending indication; remove it's handlers */ - att->pending_ind->callback = NULL; - att->pending_ind->destroy = NULL; + cancel_att_send_op(att->pending_ind); return true; } @@ -1080,17 +1088,13 @@ bool bt_att_cancel_all(struct bt_att *att) queue_remove_all(att->ind_queue, NULL, NULL, destroy_att_send_op); queue_remove_all(att->write_queue, NULL, NULL, destroy_att_send_op); - if (att->pending_req) { + if (att->pending_req) /* Don't cancel the pending request; remove it's handlers */ - att->pending_req->callback = NULL; - att->pending_req->destroy = NULL; - } + cancel_att_send_op(att->pending_req); - if (att->pending_ind) { - /* Don't cancel the pending indication; remove it's handlers */ - att->pending_ind->callback = NULL; - att->pending_ind->destroy = NULL; - } + if (att->pending_ind) + /* Don't cancel the pending request; remove it's handlers */ + cancel_att_send_op(att->pending_ind); return true; } -- 2.47.3