diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index e1adff6d..4cb81413 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -1,4 +1,5 @@ #include "app-loader.h" +#include "api-hal-delay.h" #define APP_LOADER_TAG "app_loader" @@ -7,6 +8,7 @@ typedef struct { const FlipperApplication* current_app; string_t args; Cli* cli; + size_t free_heap_size; } AppLoaderState; static AppLoaderState state; @@ -90,11 +92,29 @@ bool app_loader_start(const char* name, const char* args) { void app_loader_thread_state_callback(FuriThreadState thread_state, void* context) { furi_assert(context); - if(thread_state == FuriThreadStateStopped) { + + AppLoaderState* state = context; + + if(thread_state == FuriThreadStateRunning) { + state->free_heap_size = xPortGetFreeHeapSize(); + } else if(thread_state == FuriThreadStateStopped) { + /* + * Current Leak Sanitizer assumes that memory is allocated and freed + * inside one thread. Timers are allocated in one task, but freed in + * Timer-Task thread, and xTimerDelete() just put command to queue. + * To avoid some bad cases there are few fixes: + * 1) delay for Timer to process commands + * 2) there are 'heap diff' which shows difference in heap before task + * started and after task completed. In process of leakage monitoring + * both values should be taken into account. + */ + delay(20); + int heap_diff = state->free_heap_size - xPortGetFreeHeapSize(); FURI_LOG_I( APP_LOADER_TAG, - "Application thread stopped, heap leaked: %d", - furi_thread_get_heap_size(state.thread)); + "Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.", + heap_diff, + furi_thread_get_heap_size(state->thread)); api_hal_power_insomnia_exit(); } } diff --git a/core/furi/memmgr_heap.c b/core/furi/memmgr_heap.c index 9f190706..d8863e42 100644 --- a/core/furi/memmgr_heap.c +++ b/core/furi/memmgr_heap.c @@ -142,6 +142,7 @@ void memmgr_heap_enable_thread_trace(osThreadId_t thread_id) { MemmgrHeapAllocDict_t alloc_dict; MemmgrHeapAllocDict_init(alloc_dict); MemmgrHeapThreadDict_set_at(memmgr_heap_thread_dict, (uint32_t)thread_id, alloc_dict); + MemmgrHeapAllocDict_clear(alloc_dict); memmgr_heap_thread_trace_depth--; } (void)xTaskResumeAll();