Potential memory leak issue in NCS GATT Discovery gatt_dm, "No space for a UUID."

Hi,

I'm using the gatt_dm library in NCS v2.2.0 to manage service discovery for a project. The first connection is discovered correctly, without any issue. After that discovery process finishes and the device disconnects, I attempt to reconnect and rediscover services, but I get the error "No space for a UUID," followed by "The discovery procedure failed, err -12".

I'm not sure where I'm going wrong, I'm calling bt_gatt_dm_data_release(dm) and bt_gatt_dm_continue(dm, NULL) any time the discover_completed callback returns. They both report success. Here are a few sections of my code, but I can upload a full example project too if that works better.

static void discover_completed(struct bt_gatt_dm *dm, void *ctx)
{
	char uuid_str[37];

	const struct bt_gatt_dm_attr *gatt_service_attr =
			bt_gatt_dm_service_get(dm);
	const struct bt_gatt_service_val *gatt_service =
			bt_gatt_dm_attr_service_val(gatt_service_attr);

	int err = 0;
	//decide to continue parsing or return
	if(discovery_mode == PAIRING){
		//Check if service is DIS (for serial) or PERIPHERAL (for group #)
		//bt_uuid_cmp returns 0 if match. so, return if !(!dis || !peripheral)
		//ie, dis && peripheral
		if(bt_uuid_cmp(gatt_service->uuid, BT_UUID_DIS) && 
			bt_uuid_cmp(gatt_service->uuid, PERIPHERAL_UUID))
		{
			err = bt_gatt_dm_data_release(dm);
			NOTIFY_IF_ERR(err);
			err = bt_gatt_dm_continue(dm, NULL);
			NOTIFY_IF_ERR(err);
			return;
		}
	}
	if(discovery_mode == GROUP){
		if(bt_uuid_cmp(gatt_service->uuid, PERIPHERAL_UUID)){
			err = bt_gatt_dm_data_release(dm);
			NOTIFY_IF_ERR(err);
			err = bt_gatt_dm_continue(dm, NULL);
			NOTIFY_IF_ERR(err);
			return;
		}
	}
	uint8_t characteristic_arr[] = {0, 0};
	characteristic_arr[1] = characteristic & 0xFF;
	characteristic_arr[0] = characteristic >> 8;
	struct bt_uuid * uuid = CUSTOM_UUID(characteristic_arr[0], characteristic_arr[1]);
	bt_uuid_to_str(uuid, uuid_str, sizeof(uuid_str));
	LOG_DBG("Looking for characteristic %s", uuid_str);

	const struct bt_gatt_dm_attr *attr = NULL;
	while (NULL != (attr = bt_gatt_dm_attr_next(dm, attr))) {
		bt_uuid_to_str(attr->uuid, uuid_str, sizeof(uuid_str));
		LOG_DBG("Found characteristic %s", uuid_str);
		//Check UUIDs and handle their handles accordingly
		if(!bt_uuid_cmp(attr->uuid, SERIAL_UUID)){
			LOG_DBG("Serial UUID detected!");
			serial_handle = attr->handle;
		}
		if(!bt_uuid_cmp(attr->uuid, GROUP_UUID)){
			LOG_DBG("Group UUID detected!");
			group_num_handle = attr->handle;
		}
		if(!bt_uuid_cmp(attr->uuid, uuid)){
			LOG_DBG("Specific characteristic detected!");
			characteristic_handle = attr->handle;
		}
	}

	//Serial read request, followed by group write request, happens when DM is
	//  complete, in discover_service_not_found.
	err = bt_gatt_dm_data_release(dm);
	NOTIFY_IF_ERR(err);
	err = bt_gatt_dm_continue(dm, NULL);
	NOTIFY_IF_ERR(err);
	LOG_DBG("Returning! %d", __LINE__);
}

static void discover_service_not_found(struct bt_conn *conn, void *ctx)
{
	LOG_DBG("Service discovery all done.");
	int err = 0;
	if(discovery_mode == PAIRING){
		serial_read_params.single.handle = serial_handle;
		err = bt_gatt_read(peripheral_conn, &serial_read_params);
	}
	else if(discovery_mode == GROUP){
		if(characteristic_handle == 0xFFFF){
			notify_error_disconnect(controller_conn, -ENOENT, __LINE__);
		}
		err = characteristic_write(conn, characteristic_handle, value, write_characteristic_cb);
	}
	NOTIFY_IF_ERR(err);
}

static void discover_error_found(struct bt_conn *conn, int err, void *ctx)
{
	LOG_ERR("The discovery procedure failed, err %d\n", err);
}

static struct bt_gatt_dm_cb discover_serial_cb = {
	.completed = discover_completed,
	.service_not_found = discover_service_not_found,
	.error_found = discover_error_found,
};

static void connected(struct bt_conn *conn, uint8_t conn_err)
{
	LOG_INF("Connected!");
	if(conn == peripheral_conn){
		if(conn_err){
			LOG_ERR("Connection failed: %d",conn_err);
			bt_conn_unref(peripheral_conn);
			peripheral_conn = NULL;
			bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
			return;
		}
		// ie, peripheral device - start discovery of serial number.
		int err = bt_gatt_dm_start(conn, NULL, &discover_serial_cb, NULL);
		NOTIFY_IF_ERR(err);
	}
	else{
		if(conn_err){
			LOG_ERR("Connection failed: %d",conn_err);
			bt_conn_unref(controller_conn);
			controller_conn = NULL;
			return;
		}
		controller_conn = bt_conn_ref(conn);
	}
}

I also changed the gatt_dm log level to DBG, and put a few print statements in uuid_store to see what addresses it's allocating for the UUID buffer. I noticed that the pointers only increase and don't reset with the new connection, making me think k_free isn't being called where it should be.

I: Filters matched. Address: F64171FB4147, connectable: yes, mode: 2
I: Connected!
D: Attr: handle 1
D: Attr store, pos: 0, handle: 1
D: Service detected, handles range: <2, 9>
D: Size: 4
D: Buffer: 536904496
D: Starting descriptors discovery
D: Attr: handle 2
D: Attr store, pos: 1, handle: 2
D: Attr: handle 3
D: Attr store, pos: 2, handle: 3
D: Attr: handle 4
D: Attr store, pos: 3, handle: 4
D: Attr: handle 5
D: Attr store, pos: 4, handle: 5
D: Attr: handle 6
D: Attr store, pos: 5, handle: 6
D: Attr: handle 7
D: Attr store, pos: 6, handle: 7
D: Attr: handle 8
D: Attr store, pos: 7, handle: 8
D: Attr: handle 9
D: Attr store, pos: 8, handle: 9
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 2
D: Size: 4
D: Buffer: 536904564
D: Attr: handle 4
D: Size: 4
D: Buffer: 536904568
D: Attr: handle 6
D: Size: 4
D: Buffer: 536904572
D: Attr: handle 8
D: Size: 4
D: Buffer: 536904576
D: NULL attribute
D: Discovery complete.
D: Attr memory release
D: Returning! 287
D: Attr: handle 10
D: Attr store, pos: 0, handle: 10
D: Empty service detected with handle: 10
D: Size: 4
D: Buffer: 536904496
D: Discovery complete.
D: Attr memory release
D: Returning! 287
D: Attr: handle 11
D: Attr store, pos: 0, handle: 11
D: Service detected, handles range: <12, 14>
D: Size: 4
D: Buffer: 536904496
D: Starting descriptors discovery
D: Attr: handle 12
D: Attr store, pos: 1, handle: 12
D: Attr: handle 13
D: Attr store, pos: 2, handle: 13
D: Attr: handle 14
D: Attr store, pos: 3, handle: 14
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 12
D: Size: 17
D: Buffer: 536904536
D: NULL attribute
D: Discovery complete.
D: Attr memory release
D: Returning! 287
D: Attr: handle 15
D: Attr store, pos: 0, handle: 15
D: Service detected, handles range: <16, 42>
D: Size: 17
D: Buffer: 536904496
D: Starting descriptors discovery
D: Attr: handle 16
D: Attr store, pos: 1, handle: 16
D: Attr: handle 17
D: Attr store, pos: 2, handle: 17
D: Attr: handle 18
D: Attr store, pos: 3, handle: 18
D: Attr: handle 19
D: Attr store, pos: 4, handle: 19
D: Attr: handle 20
D: Attr store, pos: 5, handle: 20
D: Attr: handle 21
D: Attr store, pos: 6, handle: 21
D: Attr: handle 22
D: Attr store, pos: 7, handle: 22
D: Attr: handle 23
D: Attr store, pos: 8, handle: 23
D: Attr: handle 24
D: Attr store, pos: 9, handle: 24
D: Attr: handle 25
D: Attr store, pos: 10, handle: 25
D: Attr: handle 26
D: Attr store, pos: 11, handle: 26
D: Attr: handle 27
D: Attr store, pos: 12, handle: 27
D: Attr: handle 28
D: Attr store, pos: 13, handle: 28
D: Attr: handle 29
D: Attr store, pos: 14, handle: 29
D: Attr: handle 30
D: Attr store, pos: 15, handle: 30
D: Attr: handle 31
D: Attr store, pos: 16, handle: 31
D: Attr: handle 32
D: Attr store, pos: 17, handle: 32
D: Attr: handle 33
D: Attr store, pos: 18, handle: 33
D: Attr: handle 34
D: Attr store, pos: 19, handle: 34
D: Attr: handle 35
D: Attr store, pos: 20, handle: 35
D: Attr: handle 36
D: Attr store, pos: 21, handle: 36
D: Attr: handle 37
D: Attr store, pos: 22, handle: 37
D: Attr: handle 38
D: Attr store, pos: 23, handle: 38
D: Attr: handle 39
D: Attr store, pos: 24, handle: 39
D: Attr: handle 40
D: Attr store, pos: 25, handle: 40
D: Attr: handle 41
D: Attr store, pos: 26, handle: 41
D: Attr: handle 42
D: Attr store, pos: 27, handle: 42
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 16
D: Size: 17
D: Buffer: 536905000
D: Attr: handle 18
D: Size: 17
D: Buffer: 536905020
D: Attr: handle 20
D: Size: 17
D: Buffer: 536905040
D: Attr: handle 22
D: Size: 17
D: Buffer: 536905060
D: Attr: handle 24
D: Size: 17
D: Buffer: 536905080
D: Attr: handle 26
D: Size: 17
D: Buffer: 536905124
D: Attr: handle 28
D: Size: 17
D: Buffer: 536905144
D: Attr: handle 30
D: Size: 17
D: Buffer: 536905164
D: Attr: handle 32
D: Size: 17
D: Buffer: 536905184
D: Attr: handle 34
D: Size: 17
D: Buffer: 536905204
D: Attr: handle 36
D: Size: 17
D: Buffer: 536905252
D: Attr: handle 38
D: Size: 17
D: Buffer: 536905272
D: Attr: handle 40
D: Size: 17
D: Buffer: 536905292
D: NULL attribute
D: Discovery complete.
D: Looking for characteristic 00000000-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 00001522-5948-4f3b-9e29-95c3322d9d6c
D: Group UUID detected!
D: Found characteristic 2803
D: Found characteristic 00001526-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 00001527-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 00001528-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 0000152a-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 0000152b-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 0000152c-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 0000152d-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 0000152e-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 0000152f-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 00001529-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 00001530-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 00001531-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2902
D: Attr memory release
D: Returning! 341
D: Attr: handle 43
D: Attr store, pos: 0, handle: 43
D: Service detected, handles range: <44, 65535>
D: Size: 4
D: Buffer: 536904496
D: Starting descriptors discovery
D: Attr: handle 44
D: Attr store, pos: 1, handle: 44
D: Attr: handle 45
D: Attr store, pos: 2, handle: 45
D: Attr: handle 46
D: Attr store, pos: 3, handle: 46
D: Attr: handle 47
D: Attr store, pos: 4, handle: 47
D: Attr: handle 48
D: Attr store, pos: 5, handle: 48
D: Attr: handle 49
D: Attr store, pos: 6, handle: 49
D: Attr: handle 50
D: Attr store, pos: 7, handle: 50
D: Attr: handle 51
D: Attr store, pos: 8, handle: 51
D: Attr: handle 52
D: Attr store, pos: 9, handle: 52
D: Attr: handle 53
D: Attr store, pos: 10, handle: 53
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 44
D: Size: 4
D: Buffer: 536904580
D: Attr: handle 46
D: Size: 4
D: Buffer: 536904584
D: Attr: handle 48
D: Size: 4
D: Buffer: 536904588
D: Attr: handle 50
D: Size: 4
D: Buffer: 536904592
D: Attr: handle 52
D: Size: 4
D: Buffer: 536904596
D: NULL attribute
D: Discovery complete.
D: Looking for characteristic 00000000-5948-4f3b-9e29-95c3322d9d6c
D: Found characteristic 2803
D: Found characteristic 2a29
D: Found characteristic 2803
D: Found characteristic 2a24
D: Found characteristic 2803
D: Found characteristic 2a25
D: Serial UUID detected!
D: Found characteristic 2803
D: Found characteristic 2a27
D: Found characteristic 2803
D: Found characteristic 2a26
D: Attr memory release
D: Discover complete. No service found.
D: Attr memory release
D: Service discovery all done.
D: Returning! 341
D: Received serial number P-L2C-000000001 on address F64171FB4147
I: Stored new serial mapping.
I: Group number sent.
I: Disconnected: (reason 22)
I: Disconnected from peripheral.
D: Setting PSR value to 0x1
I: Disconnected: (reason 22)
I: Disconnected from controller.
W: opcode 0x200a status 0x09

// Here is where the second connection attempt starts.
I: Connected!
I: Running packet_rx_cb...
I: Packet received!

D: PAIRING packet contents: Address F64171FB4147, group num 1
I: Filters matched. Address: F64171FB4147, connectable: yes, mode: 2
I: Connected!
D: Attr: handle 1
D: Attr store, pos: 0, handle: 1
D: Service detected, handles range: <2, 9>
D: Size: 4
D: Buffer: 536904608
D: Starting descriptors discovery
D: Attr: handle 2
D: Attr store, pos: 1, handle: 2
D: Attr: handle 3
D: Attr store, pos: 2, handle: 3
D: Attr: handle 4
D: Attr store, pos: 3, handle: 4
D: Attr: handle 5
D: Attr store, pos: 4, handle: 5
D: Attr: handle 6
D: Attr store, pos: 5, handle: 6
D: Attr: handle 7
D: Attr store, pos: 6, handle: 7
D: Attr: handle 8
D: Attr store, pos: 7, handle: 8
D: Attr: handle 9
D: Attr store, pos: 8, handle: 9
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 2
D: Size: 4
D: Buffer: 536904676
D: Attr: handle 4
D: Size: 4
D: Buffer: 536904680
D: Attr: handle 6
D: Size: 4
D: Buffer: 536904684
D: Attr: handle 8
D: Size: 4
D: Buffer: 536904688
D: NULL attribute
D: Discovery complete.
D: Attr memory release
D: Returning! 287
D: Attr: handle 10
D: Attr store, pos: 0, handle: 10
D: Empty service detected with handle: 10
D: Size: 4
D: Buffer: 536904608
D: Discovery complete.
D: Attr memory release
D: Returning! 287
D: Attr: handle 11
D: Attr store, pos: 0, handle: 11
D: Service detected, handles range: <12, 14>
D: Size: 4
D: Buffer: 536904608
D: Starting descriptors discovery
D: Attr: handle 12
D: Attr store, pos: 1, handle: 12
D: Attr: handle 13
D: Attr store, pos: 2, handle: 13
D: Attr: handle 14
D: Attr store, pos: 3, handle: 14
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 12
D: Size: 17
D: Buffer: 536904648
D: NULL attribute
D: Discovery complete.
D: Attr memory release
D: Returning! 287
D: Attr: handle 15
D: Attr store, pos: 0, handle: 15
D: Service detected, handles range: <16, 42>
D: Size: 17
D: Buffer: 536904608
D: Starting descriptors discovery
D: Attr: handle 16
D: Attr store, pos: 1, handle: 16
D: Attr: handle 17
D: Attr store, pos: 2, handle: 17
D: Attr: handle 18
D: Attr store, pos: 3, handle: 18
D: Attr: handle 19
D: Attr store, pos: 4, handle: 19
D: Attr: handle 20
D: Attr store, pos: 5, handle: 20
D: Attr: handle 21
D: Attr store, pos: 6, handle: 21
D: Attr: handle 22
D: Attr store, pos: 7, handle: 22
D: Attr: handle 23
D: Attr store, pos: 8, handle: 23
D: Attr: handle 24
D: Attr store, pos: 9, handle: 24
D: Attr: handle 25
D: Attr store, pos: 10, handle: 25
D: Attr: handle 26
D: Attr store, pos: 11, handle: 26
D: Attr: handle 27
D: Attr store, pos: 12, handle: 27
D: Attr: handle 28
D: Attr store, pos: 13, handle: 28
D: Attr: handle 29
D: Attr store, pos: 14, handle: 29
D: Attr: handle 30
D: Attr store, pos: 15, handle: 30
D: Attr: handle 31
D: Attr store, pos: 16, handle: 31
D: Attr: handle 32
D: Attr store, pos: 17, handle: 32
D: Attr: handle 33
D: Attr store, pos: 18, handle: 33
D: Attr: handle 34
D: Attr store, pos: 19, handle: 34
D: Attr: handle 35
D: Attr store, pos: 20, handle: 35
D: Attr: handle 36
D: Attr store, pos: 21, handle: 36
D: Attr: handle 37
D: Attr store, pos: 22, handle: 37
D: Attr: handle 38
D: Attr store, pos: 23, handle: 38
D: Attr: handle 39
D: Attr store, pos: 24, handle: 39
D: Attr: handle 40
D: Attr store, pos: 25, handle: 40
D: Attr: handle 41
D: Attr store, pos: 26, handle: 41
D: Attr: handle 42
D: Attr store, pos: 27, handle: 42
D: NULL attribute
D: Starting characteristic discovery
D: Attr: handle 16
D: Size: 17
D: Buffer: 536905112
D: Attr: handle 18
D: Size: 17
D: Buffer: 536905132
D: Attr: handle 20
D: Size: 17
D: Buffer: 536905152
D: Attr: handle 22
D: Size: 17
D: Buffer: 536905172
D: Attr: handle 24
D: Size: 17
D: Buffer: 536905192
D: Attr: handle 26
D: Size: 17
D: Buffer: 536905236
D: Attr: handle 28
D: Size: 17
D: Buffer: 536905256
D: Attr: handle 30
D: Size: 17
D: Buffer: 536905276
D: Attr: handle 32
D: Size: 17
D: Buffer: 536905296
D: Attr: handle 34
D: Size: 17
D: Buffer: 536905316
D: Attr: handle 36
D: Size: 17
D: Buffer: 0
E: No space for a UUID.
D: Attr memory release
E: The discovery procedure failed, err -12

Using Nordic Connect SDK v2.2.0 with VSCode on nRF52832 dev kit PCA10040 3.0.0.

Thank you, and let me know if there's any other information I can provide to assist in debugging this problem.

Ella

Parents
  • Hi,

    Thank you for providing a detailed description. I reviewed the code and log you provided, and it seems that the buffer is being freed correctly up until address 536904596, just before the disconnect. However, I couldn't find any errors in your code. I also attempted to reproduce the issue using the 'peripheral_gatt_dm' sample, but unfortunately, I was unsuccessful.

    Have you tried this with the 'peripheral_gatt_dm' sample as well?

    Best regards,

    Vidar

  • Hi,

    I tried building a simple example based on this code without some of the other functionality, and that works as expected. I'll continue looking into it to determine which part of the code causes this error, and I'll update the ticket once I know more.

    Thank you!
    Ella

Reply Children
Related