Re-using static TCB race condition

berman5 wrote on Tuesday, November 27, 2018:

Let me preface this post that I’m not sure if this behavior that ought to be supported by FreeRTOS, but it’s what I’ve been stuck with working with.

I have some code that re-uses a statically allocated TCB and that statically allocated task is allowed to delete itself. After it deletes itself, the “parent” task re-uses that TCB for a different task (e.g. calls xTaskCreateStatic with the same TCB/stack).

The issue I’ve discovered is that if the idle task isn’t able to clean up and remove this TCB from the xTasksWaitingTermination list by the time the “parent” task calls xTaskCreateStatic, it’ll come along and potentially corrupt another task list (e.g. ready/suspended). This is because xTaskCreateStatic assumes that the TCB isn’t in any meaningful list and adds the freshly minted TCB to the ready list. When the idle task does eventually come along to clean up the task, xTasksWaitingTermination ends up pointing to part of another list (e.g. ready/suspended) and causing the idle task to run prvDeleteTCB on some of those TCBs (depending on if uxDeletedTasksWaitingCleanUp dictates that there’s more tasks to clean up), ultimately causing a system crash. I’ve been able to reproduce this issue on my MCU platform (an environment based on the Xilinx Zynq 7000) and on the Windows simulator.

Is there a way to ensure that the static TCB is safe to use? My current workaround has been to modify xTaskCreateStatic to check if the supplied TCB is on the xTasksWaitingTermination list and do the removal/cleanup that the idle task would’ve done otherwise.

rtel wrote on Wednesday, November 28, 2018:

There are various macros pre and post clean up of a TCB - perhaps define
one of those to do something to the TCB structure that lets you know if
it has been cleaned up yet or not? For example, set the name to NULL
(first character to 0x00).

rtel wrote on Wednesday, November 28, 2018:

Should have said if you define the macros in FreeRTOSConfig.h they will
get included in the correct order.

berman5 wrote on Wednesday, November 28, 2018:

I thought about doing something to that effect (adding a thread-local storage pointer), but was afraid that I’d be inverting the priority of the task trying to re-use the TCB into the idle task priority since it’d be polling the idle task to see if it’s completed some work.