ble_mesh: Fix memory leak when node is reset
When node is being reset, the init functions of each sig-defined models will be invoked again, this will cause memory leak because some model internal data will be allocated again. Hence before trying to allocate memory for them, we add some check to make sure no memory has been allocated previously. And for client model, when the init functions are invoked again, we will clear the list items.
This commit is contained in:
parent
6c0044cc65
commit
3b9fe36494
9 changed files with 132 additions and 85 deletions
|
@ -1649,20 +1649,23 @@ int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked*/
|
if (!client->internal_data) {
|
||||||
internal = osi_calloc(sizeof(config_internal_data_t));
|
internal = osi_calloc(sizeof(config_internal_data_t));
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
BT_ERR("Allocate memory for Configuration Client internal data fail");
|
BT_ERR("Allocate memory for Configuration Client internal data fail");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_slist_init(&internal->queue);
|
||||||
|
|
||||||
|
client->model = model;
|
||||||
|
client->op_pair_size = ARRAY_SIZE(cfg_op_pair);
|
||||||
|
client->op_pair = cfg_op_pair;
|
||||||
|
client->internal_data = internal;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(client->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&internal->queue);
|
|
||||||
|
|
||||||
client->model = model;
|
|
||||||
client->op_pair_size = ARRAY_SIZE(cfg_op_pair);
|
|
||||||
client->op_pair = cfg_op_pair;
|
|
||||||
client->internal_data = internal;
|
|
||||||
|
|
||||||
cli = client;
|
cli = client;
|
||||||
|
|
||||||
/* Configuration Model security is device-key based */
|
/* Configuration Model security is device-key based */
|
||||||
|
|
|
@ -454,20 +454,23 @@ int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked*/
|
if (!client->internal_data) {
|
||||||
internal = osi_calloc(sizeof(health_internal_data_t));
|
internal = osi_calloc(sizeof(health_internal_data_t));
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_slist_init(&internal->queue);
|
||||||
|
|
||||||
|
client->model = model;
|
||||||
|
client->op_pair_size = ARRAY_SIZE(health_op_pair);
|
||||||
|
client->op_pair = health_op_pair;
|
||||||
|
client->internal_data = internal;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(client->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&internal->queue);
|
|
||||||
|
|
||||||
client->model = model;
|
|
||||||
client->op_pair_size = ARRAY_SIZE(health_op_pair);
|
|
||||||
client->op_pair = health_op_pair;
|
|
||||||
client->internal_data = internal;
|
|
||||||
|
|
||||||
bt_mesh_health_client_mutex_new();
|
bt_mesh_health_client_mutex_new();
|
||||||
|
|
||||||
/* Set the default health client pointer */
|
/* Set the default health client pointer */
|
||||||
|
|
|
@ -266,19 +266,22 @@ int bt_mesh_client_init(struct bt_mesh_model *model)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked */
|
if (!cli->internal_data) {
|
||||||
data = osi_calloc(sizeof(bt_mesh_client_internal_data_t));
|
data = osi_calloc(sizeof(bt_mesh_client_internal_data_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init the client data queue */
|
||||||
|
sys_slist_init(&data->queue);
|
||||||
|
|
||||||
|
cli->model = model;
|
||||||
|
cli->internal_data = data;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(cli->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init the client data queue */
|
|
||||||
sys_slist_init(&data->queue);
|
|
||||||
|
|
||||||
cli->model = model;
|
|
||||||
cli->internal_data = data;
|
|
||||||
|
|
||||||
bt_mesh_client_model_mutex_new();
|
bt_mesh_client_model_mutex_new();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -316,6 +319,28 @@ int bt_mesh_client_free_node(bt_mesh_client_node_t *node)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bt_mesh_client_clear_list(void *data)
|
||||||
|
{
|
||||||
|
bt_mesh_client_internal_data_t *internal = NULL;
|
||||||
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
BT_ERR("%s, Invalid parameter", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal = (bt_mesh_client_internal_data_t *)data;
|
||||||
|
|
||||||
|
bt_mesh_list_lock();
|
||||||
|
while (!sys_slist_is_empty(&internal->queue)) {
|
||||||
|
node = (void *)sys_slist_get_not_empty(&internal->queue);
|
||||||
|
osi_free(node);
|
||||||
|
}
|
||||||
|
bt_mesh_list_unlock();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int bt_mesh_set_client_model_role(bt_mesh_role_param_t *common)
|
int bt_mesh_set_client_model_role(bt_mesh_role_param_t *common)
|
||||||
{
|
{
|
||||||
bt_mesh_client_user_data_t *client = NULL;
|
bt_mesh_client_user_data_t *client = NULL;
|
||||||
|
|
|
@ -1172,20 +1172,23 @@ static int generic_client_init(struct bt_mesh_model *model, bool primary)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked*/
|
if (!client->internal_data) {
|
||||||
internal = osi_calloc(sizeof(generic_internal_data_t));
|
internal = osi_calloc(sizeof(generic_internal_data_t));
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_slist_init(&internal->queue);
|
||||||
|
|
||||||
|
client->model = model;
|
||||||
|
client->op_pair_size = ARRAY_SIZE(gen_op_pair);
|
||||||
|
client->op_pair = gen_op_pair;
|
||||||
|
client->internal_data = internal;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(client->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&internal->queue);
|
|
||||||
|
|
||||||
client->model = model;
|
|
||||||
client->op_pair_size = ARRAY_SIZE(gen_op_pair);
|
|
||||||
client->op_pair = gen_op_pair;
|
|
||||||
client->internal_data = internal;
|
|
||||||
|
|
||||||
bt_mesh_generic_client_mutex_new();
|
bt_mesh_generic_client_mutex_new();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -108,6 +108,8 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model,
|
||||||
|
|
||||||
int bt_mesh_client_free_node(bt_mesh_client_node_t *node);
|
int bt_mesh_client_free_node(bt_mesh_client_node_t *node);
|
||||||
|
|
||||||
|
int bt_mesh_client_clear_list(void *data);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NODE = 0,
|
NODE = 0,
|
||||||
PROVISIONER,
|
PROVISIONER,
|
||||||
|
|
|
@ -1362,20 +1362,23 @@ static int light_client_init(struct bt_mesh_model *model, bool primary)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked*/
|
if (!client->internal_data) {
|
||||||
internal = osi_calloc(sizeof(light_internal_data_t));
|
internal = osi_calloc(sizeof(light_internal_data_t));
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_slist_init(&internal->queue);
|
||||||
|
|
||||||
|
client->model = model;
|
||||||
|
client->op_pair_size = ARRAY_SIZE(light_op_pair);
|
||||||
|
client->op_pair = light_op_pair;
|
||||||
|
client->internal_data = internal;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(client->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&internal->queue);
|
|
||||||
|
|
||||||
client->model = model;
|
|
||||||
client->op_pair_size = ARRAY_SIZE(light_op_pair);
|
|
||||||
client->op_pair = light_op_pair;
|
|
||||||
client->internal_data = internal;
|
|
||||||
|
|
||||||
bt_mesh_light_client_mutex_new();
|
bt_mesh_light_client_mutex_new();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -604,20 +604,23 @@ int bt_mesh_sensor_cli_init(struct bt_mesh_model *model, bool primary)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked*/
|
if (!client->internal_data) {
|
||||||
internal = osi_calloc(sizeof(sensor_internal_data_t));
|
internal = osi_calloc(sizeof(sensor_internal_data_t));
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_slist_init(&internal->queue);
|
||||||
|
|
||||||
|
client->model = model;
|
||||||
|
client->op_pair_size = ARRAY_SIZE(sensor_op_pair);
|
||||||
|
client->op_pair = sensor_op_pair;
|
||||||
|
client->internal_data = internal;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(client->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&internal->queue);
|
|
||||||
|
|
||||||
client->model = model;
|
|
||||||
client->op_pair_size = ARRAY_SIZE(sensor_op_pair);
|
|
||||||
client->op_pair = sensor_op_pair;
|
|
||||||
client->internal_data = internal;
|
|
||||||
|
|
||||||
bt_mesh_sensor_client_mutex_new();
|
bt_mesh_sensor_client_mutex_new();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -667,20 +667,23 @@ static int time_scene_client_init(struct bt_mesh_model *model, bool primary)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: call osi_free() when deinit function is invoked*/
|
if (!client->internal_data) {
|
||||||
internal = osi_calloc(sizeof(time_scene_internal_data_t));
|
internal = osi_calloc(sizeof(time_scene_internal_data_t));
|
||||||
if (!internal) {
|
if (!internal) {
|
||||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_slist_init(&internal->queue);
|
||||||
|
|
||||||
|
client->model = model;
|
||||||
|
client->op_pair_size = ARRAY_SIZE(time_scene_op_pair);
|
||||||
|
client->op_pair = time_scene_op_pair;
|
||||||
|
client->internal_data = internal;
|
||||||
|
} else {
|
||||||
|
bt_mesh_client_clear_list(client->internal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&internal->queue);
|
|
||||||
|
|
||||||
client->model = model;
|
|
||||||
client->op_pair_size = ARRAY_SIZE(time_scene_op_pair);
|
|
||||||
client->op_pair = time_scene_op_pair;
|
|
||||||
client->internal_data = internal;
|
|
||||||
|
|
||||||
bt_mesh_time_scene_client_mutex_new();
|
bt_mesh_time_scene_client_mutex_new();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -193,8 +193,10 @@ void bt_mesh_server_alloc_ctx(struct k_work *work)
|
||||||
* Here we use the allocated heap memory to store the "struct bt_mesh_msg_ctx".
|
* Here we use the allocated heap memory to store the "struct bt_mesh_msg_ctx".
|
||||||
*/
|
*/
|
||||||
__ASSERT(work, "%s, Invalid parameter", __func__);
|
__ASSERT(work, "%s, Invalid parameter", __func__);
|
||||||
work->_reserved = osi_calloc(sizeof(struct bt_mesh_msg_ctx));
|
if (!work->_reserved) {
|
||||||
__ASSERT(work->_reserved, "%s, Failed to allocate memory", __func__);
|
work->_reserved = osi_calloc(sizeof(struct bt_mesh_msg_ctx));
|
||||||
|
__ASSERT(work->_reserved, "%s, Failed to allocate memory", __func__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bt_mesh_is_server_recv_last_msg(struct bt_mesh_last_msg_info *last,
|
bool bt_mesh_is_server_recv_last_msg(struct bt_mesh_last_msg_info *last,
|
||||||
|
|
Loading…
Reference in a new issue