xTaskCreate() in utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c ignores a failure from tx_thread_resume():
ret = tx_thread_resume(&p_task->thread);
if(ret != TX_SUCCESS) {
TX_FREERTOS_ASSERT_FAIL();
}
TX_DISABLE;
g_txfr_task_count++;
TX_RESTORE;
return pdPASS;
With the default configuration, where TX_FREERTOS_ASSERT_FAIL() expands to nothing, the function counts the task and returns pdPASS. The caller is told the task started, and holds a handle to a task that exists, occupies its stack and task structure, is counted by uxTaskGetNumberOfTasks(), and will never run.
Inconsistency
xTaskCreateStatic() treats the same failure as fatal and returns NULL. After #584 it also unwinds the thread and the notification semaphore before doing so. The two functions now disagree about what a resume failure means, which is the part that most wants a decision.
The question behind it
This is not simply a missing error path. Deciding it means deciding what a caller may expect from a task that exists but is not scheduled:
- If the resume failure should propagate,
xTaskCreate() should unwind the thread, the semaphore and both allocations, and return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY or a similar failure, matching what the static variant does.
- If a created but unstarted task is considered acceptable, then
xTaskCreateStatic() is the one that is wrong to fail, and the behaviour should be documented either way.
FreeRTOS itself has no equivalent state to model here, since xTaskCreate() there does not have a separate resume step, so this is a decision about the compatibility layer rather than a compatibility question.
Notes
Found while writing the static creation tests in #584. Left out of that PR because it is a behavioural change rather than a leak fix, and #584 was scoped to resources abandoned on error paths.
xTaskCreate()inutility/rtos_compatibility_layers/FreeRTOS/tx_freertos.cignores a failure fromtx_thread_resume():With the default configuration, where
TX_FREERTOS_ASSERT_FAIL()expands to nothing, the function counts the task and returnspdPASS. The caller is told the task started, and holds a handle to a task that exists, occupies its stack and task structure, is counted byuxTaskGetNumberOfTasks(), and will never run.Inconsistency
xTaskCreateStatic()treats the same failure as fatal and returnsNULL. After #584 it also unwinds the thread and the notification semaphore before doing so. The two functions now disagree about what a resume failure means, which is the part that most wants a decision.The question behind it
This is not simply a missing error path. Deciding it means deciding what a caller may expect from a task that exists but is not scheduled:
xTaskCreate()should unwind the thread, the semaphore and both allocations, and returnerrCOULD_NOT_ALLOCATE_REQUIRED_MEMORYor a similar failure, matching what the static variant does.xTaskCreateStatic()is the one that is wrong to fail, and the behaviour should be documented either way.FreeRTOS itself has no equivalent state to model here, since
xTaskCreate()there does not have a separate resume step, so this is a decision about the compatibility layer rather than a compatibility question.Notes
Found while writing the static creation tests in #584. Left out of that PR because it is a behavioural change rather than a leak fix, and #584 was scoped to resources abandoned on error paths.