This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VH-Q1: appRtosTaskDelete() bug report

Part Number: TDA4VH-Q1

Just faced an issue with j784s4 PSDK  11.2 (likely also on other versions and SoCs that use pdk).

Problem: got R5+safertos hangs short after clean termination of a task, via appRtosTaskDelete().

After a long debugging session, found that root cause is:

  • in appRtosTaskCreate(), the tsk is automatically registered in perfstats, via appPerfStatsRegisterTask(),
  • but this is not undone in appRtosTaskDelete(), resulting into a dangling task pointer inside perfstats,
  • later this is causing a crash.

Below is a patch adding reverse operation for appRtosTaskDelete(), that made the issue to no longer reproduce.

Date: Fri, 15 May 2026 18:48:07 +0200
Subject: [PATCH] app_utils: perfstat: survive after task termination

Since appRtosTaskCreate() autoimatically adds the created task to
perfstat, appRtosTaskDelete() shall remove it. Otherwise, a
dangling task pointer is left in perfstat, causing crashes.
---
 .../utils/perf_stats/include/app_perf_stats.h |  9 +++++
 .../utils/perf_stats/src/app_perf_stats_api.c |  6 +++
 .../perf_stats/src/app_perf_stats_api_x86.c   |  5 +++
 .../perf_stats/src/app_perf_stats_freertos.c  | 37 +++++++++++++++++++
 app_utils/utils/rtos/src/app_rtos_pdk.c       |  2 +
 5 files changed, 59 insertions(+)

diff --git a/app_utils/utils/perf_stats/include/app_perf_stats.h b/app_utils/utils/perf_stats/include/app_perf_stats.h
index 8ac585da1..a74a0604e 100755
--- a/app_utils/utils/perf_stats/include/app_perf_stats.h
+++ b/app_utils/utils/perf_stats/include/app_perf_stats.h
@@ -505,6 +505,15 @@ int32_t appPerfStatsPrintAll();
  */
 int32_t appPerfStatsRegisterTask(void *task_handle, const char *name);
 
+/**
+ * \brief Unregister a task from task load calculation
+ *
+ *        Must be called for terminated task
+ *
+ * \return 0 on success
+ */
+int32_t appPerfStatsUnregisterTask(void *task_handle);
+
 /**
  * \brief De-Initialize perf statistics collector module
  *
diff --git a/app_utils/utils/perf_stats/src/app_perf_stats_api.c b/app_utils/utils/perf_stats/src/app_perf_stats_api.c
index e1138f61f..fed4d0d02 100644
--- a/app_utils/utils/perf_stats/src/app_perf_stats_api.c
+++ b/app_utils/utils/perf_stats/src/app_perf_stats_api.c
@@ -685,6 +685,12 @@ int32_t appPerfStatsRegisterTask(void *task_handle, const char *name)
     /* NOT supported for LINUX */
     return -1;
 }
+
+int32_t appPerfStatsUnregisterTask(void *task_handle)
+{
+    /* NOT supported for LINUX */
+    return -1;
+}
 #endif
 
 void appPerfPointSetName(app_perf_point_t *prm, const char *name)
diff --git a/app_utils/utils/perf_stats/src/app_perf_stats_api_x86.c b/app_utils/utils/perf_stats/src/app_perf_stats_api_x86.c
index 523f21058..e1fd20316 100644
--- a/app_utils/utils/perf_stats/src/app_perf_stats_api_x86.c
+++ b/app_utils/utils/perf_stats/src/app_perf_stats_api_x86.c
@@ -125,6 +125,11 @@ int32_t appPerfStatsRegisterTask(void *task_handle, const char *name)
     return 0;
 }
 
+int32_t appPerfStatsUnregisterTask(void *task_handle)
+{
+    return 0;
+}
+
 void appPerfPointSetName(app_perf_point_t *prm, const char *name)
 {
 }
diff --git a/app_utils/utils/perf_stats/src/app_perf_stats_freertos.c b/app_utils/utils/perf_stats/src/app_perf_stats_freertos.c
index 374f322f9..d0b7825ff 100644
--- a/app_utils/utils/perf_stats/src/app_perf_stats_freertos.c
+++ b/app_utils/utils/perf_stats/src/app_perf_stats_freertos.c
@@ -723,6 +723,43 @@ int32_t appPerfStatsRegisterTask(void *task_handle, const char *name)
     return status;
 }
 
+int32_t appPerfStatsUnregisterTask(void *task_handle)
+{
+    app_perf_stats_obj_t *obj = &g_app_perf_stats_obj;
+    int32_t status = -1;
+    uint32_t idx;
+
+    if (1U == g_perf_stats_load_update_enable)
+    {
+        appPerfStatsLock(obj);
+
+        for (idx = 0; idx < obj->num_tasks; idx++)
+        {
+            if (obj->task_handle[idx] == task_handle)
+            {
+                status = 0;
+                break;
+            }
+        }
+
+        if (status == 0)
+        {
+            for (idx++; idx < obj->num_tasks; idx++)
+            {
+                obj->task_handle[idx - 1] = obj->task_handle[idx];
+                memcpy(obj->task_name[idx - 1], obj->task_name[idx], APP_PERF_STATS_TASK_NAME_MAX);
+                obj->taskLoad[idx - 1] = obj->taskLoad[idx];
+            }
+
+            obj->num_tasks--;
+        }
+
+        appPerfStatsUnLock(obj);
+    }
+
+    return status;
+}
+
 void appPerfStatsHwaResetLoadCalc(app_perf_hwa_id_t id)
 {
     app_perf_stats_obj_t *obj = &g_app_perf_stats_obj;
diff --git a/app_utils/utils/rtos/src/app_rtos_pdk.c b/app_utils/utils/rtos/src/app_rtos_pdk.c
index 994b78285..592d3fe42 100755
--- a/app_utils/utils/rtos/src/app_rtos_pdk.c
+++ b/app_utils/utils/rtos/src/app_rtos_pdk.c
@@ -271,6 +271,8 @@ app_rtos_status_t appRtosTaskDelete(app_rtos_task_handle_t *handle)
 
     if ((NULL != handle) && (*handle != NULL))
     {
+        (void)appPerfStatsUnregisterTask(*handle);
+
 /* LDRA_JUSTIFY_START
 <metric start> branch <metric end>
 <justification start> APP_UTILS_BRANCH_COVERAGE_RTOS_PDK_UBR002
-- 
2.47.3

  • Hi Nikitha,

    • in appRtosTaskCreate(), the tsk is automatically registered in perfstats, via appPerfStatsRegisterTask(),
    • but this is not undone in appRtosTaskDelete(), resulting into a dangling task pointer inside perfstats,
    • later this is causing a crash.

    Yes, you are correct. it seems to be a bug. I will raise a jira to fix this. Thank you for pointing it out.

    Regards,
    Gokul