Memory leak in mesh_stop()?

Snedig
Posts: 24
Joined: Sat Apr 04, 2020 3:18 pm

Memory leak in mesh_stop()?

Postby Snedig » Fri Jan 01, 2021 5:03 pm

HI,

I've been working with ESP-MESH in ESP-IDF for some time, but I'm having a hard time because I need to turn off the mesh periodically (I only synchronize with the mesh a couple of times a day).

Originally I tried to simply do:
Disconnect:

Code: Select all

ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_set_self_organized(0, 0));
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_disconnect());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_scan_stop());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_disconnect());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_stop());
Connect:

Code: Select all

ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_start());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_set_self_organized(1, 0));
However, this never manages to connect for some reason.

I have however managed to make it reconnect with the following routine:
mesh_disable():

Code: Select all

ESP_LOGW(MESH_TAG, "Disabling mesh network, heap: %u", esp_get_free_heap_size());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_flush_upstream_packets());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_flush_scan_result());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_stop());
vTaskDelay(100 / portTICK_PERIOD_MS);
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_comm_p2p_stop());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_stop());
mesh_enable():

Code: Select all

ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_start());
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_init());
ESP_ERROR_CHECK_WITHOUT_ABORT(setup_root());
mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT();
memcpy((uint8_t *)&cfg.mesh_id, mesh_settings.id, 6);
cfg.channel = mesh_settings.channel;
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_set_ap_authmode(mesh_settings.auth_mode));
cfg.mesh_ap.max_connection = mesh_settings.max_conn;
memcpy((uint8_t *)&cfg.mesh_ap.password, mesh_settings.ap_pass, strlen(mesh_settings.ap_pass));
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_set_config(&cfg));
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_start());
mesh_on = true;
if (!mesh_initialized) {
  ESP_ERROR_CHECK_WITHOUT_ABORT(esp_read_mac(mesh_self_addr.addr, 0));
}
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_mesh_set_self_organized(true, false));
This however has the problem that it seems to not free a generic queue created by esp_mesh_start() every time, leading to a memory leak that eventually makes my firmware crash.

Excerpt from:

Code: Select all

heap_trace_start(HEAP_TRACE_LEAKS);
mesh_enable();
vTaskDelay(12000 / portTICK_PERIOD_MS);
mesh_disable();
heap_trace_stop();
heap_trace_dump();

Code: Select all

7 allocations trace (300 entry buffer)
92 bytes (@ 0x3ffe19bc) allocated CPU 0 ccount 0x3d05dc14 caller 0x4009081a:0x40090ac7
0x4009081a: xQueueGenericCreate at C:/Users/prebe/esp-idf/esp-idf/components/freertos/queue.c:407

0x40090ac7: xQueueCreateMutex at C:/Users/prebe/esp-idf/esp-idf/components/freertos/queue.c:519

16 bytes (@ 0x3ffd64a8) allocated CPU 0 ccount 0x7d732308 caller 0x400f4530:0x400f45ae
0x400f4530: mem_malloc at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/mem.c:237

0x400f45ae: do_memp_malloc_pool at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/memp.c:254

16 bytes (@ 0x3ffd6458) allocated CPU 0 ccount 0x7d74713c caller 0x400f4530:0x400f45ae
0x400f4530: mem_malloc at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/mem.c:237

0x400f45ae: do_memp_malloc_pool at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/memp.c:254

16 bytes (@ 0x3ffd6480) allocated CPU 0 ccount 0x7d75beb0 caller 0x400f4530:0x400f45ae
0x400f4530: mem_malloc at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/mem.c:237

0x400f45ae: do_memp_malloc_pool at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/memp.c:254

16 bytes (@ 0x3ffd6494) allocated CPU 0 ccount 0x7d770d94 caller 0x400f4530:0x400f45ae
0x400f4530: mem_malloc at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/mem.c:237

0x400f45ae: do_memp_malloc_pool at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/memp.c:254

16 bytes (@ 0x3ffd6430) allocated CPU 0 ccount 0x7d785d9c caller 0x400f4530:0x400f45ae
0x400f4530: mem_malloc at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/mem.c:237

0x400f45ae: do_memp_malloc_pool at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/memp.c:254

16 bytes (@ 0x3ffd646c) allocated CPU 0 ccount 0x7d79ab20 caller 0x400f4530:0x400f45ae
0x400f4530: mem_malloc at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/mem.c:237

0x400f45ae: do_memp_malloc_pool at C:/Users/prebe/esp-idf/esp-idf/components/lwip/lwip/src/core/memp.c:254

188 bytes 'leaked' in trace (7 allocations)
total allocations 764 total frees 767
E (00:01:42.331) core: Memory min change: -92
E (00:01:42.332) core: Memory change: -92
E (00:01:42.332) core: Memory: 105156
The LWIP-stuff seems to be dynamically allocated buffers, and these don't seem to be a true leak, they just don't necessarily get freed at the same time.

Does anyone know how I can get this queue freed? I am currently unable to get anywhere in preventing this memory leak.

Snedig
Posts: 24
Joined: Sat Apr 04, 2020 3:18 pm

Re: Memory leak in mesh_stop()?

Postby Snedig » Sat Jan 02, 2021 7:06 am

Here is a deeper trace of the queue that is never freed:

Code: Select all

92 bytes (@ 0x3ffe4624) allocated CPU 0 ccount 0xf05736e0 caller 0x40090a9e:0x40090d4b:0x400f2a54:0x40113def:0x400ded6e:0x400db4d0
0x40090a9e: xQueueGenericCreate at C:/Users/prebe/esp-idf/esp-idf/components/freertos/queue.c:407

0x40090d4b: xQueueCreateMutex at C:/Users/prebe/esp-idf/esp-idf/components/freertos/queue.c:519

0x400f2a54: mutex_create_wrapper at C:/Users/prebe/esp-idf/esp-idf/components/esp_wifi/esp32/esp_adapter.c:326

0x40113def: esp_mesh_start at ??:?

0x400ded6e: mesh_enable at E:\ESP\projects\clean\template-app\build/../main/mesh_net.c:600 (discriminator 3)
The queue is created in esp_mesh_start(), but never seems to be freed in either esp_mesh_stop() or esp_mesh_deinit().

Who is online

Users browsing this forum: jcolebaker and 140 guests