Better exit from task

ta8086 wrote on Thursday, September 12, 2013:

Currently, if someone is terminating a task, it is necessary to delete it before end of task function. Otherwise a HardFault exception will occur. I think it is very simple to make “automatic” (in FreeRTOS) finishing of tasks - to finish function without exceptions or at least to jump in predefined error routine. Currently thousands of people waste hours and days to discover the simple reason for HardFaults - including me recently for second time (created a new task but had forgotten to delete/while(1) the task).

rtel wrote on Thursday, September 12, 2013:

Yes, on one processor it is very easy to have the task function’s return address return the task to a clean exit point.  FreeRTOS supports some 34 architecture cores though, and how this is implemented directly will be different on each one. 

It is well documented that you must not run off the end of a task, but if people are doing that, then maybe there could be a compromise solution that is portable by adding a common task entry point that includes a call to vTaskDelete() if it is ever exited.  Something like:

void vCommonTaskEntryPoint( void *pvUserTaskCode, void *pvUserTaskParameters )
    /* Start the task. */
    pvUserTaskCode( pvUserTaskParameters );

    /* If the user routine ever exits ensure the task is deleted cleanly. */
    vTaskDelete( NULL );

If you want that possibility to be investigated for feasibility then please add a feature request using the SourceForge feature request tracker.


davedoors wrote on Thursday, September 12, 2013:

That would not be a good solution because it creates a stack frame on each task’s stack that persists for the lifetime of the task but is never actually used.

richard_damon wrote on Friday, September 13, 2013:

Let me point out some of the costs to make vTaskDelete be called automatically if a task function returns:

1) It will likely cost stack space on many processors to build a stack frame to use for the return.

2) If means it will be impossible to exclude to code for vTaskDelete from the program image.

3) This means that you must also include vPortFree in the program image

4) This means that you can’t use heap1.c, the simplest (and smallest) heap implementation.

This is a fairly high cost to impose on all users to help people who don’t read the documentation.

What might make sense is that on those ports that it is cheap to do so, set the return address to go to a function that just hangs (loop forever), with a comment that if you get hear some task returned without deleting itself. There are likely some ports where this isn’t cheep enough, so it shouldn’t be promised behavior.

ta8086 wrote on Friday, September 13, 2013:

OK, but it is not necessary to call vTaskDelete automatically. It is enough to add only a return address in the beginning of the stack before calling the task function. This return address will point to a default “blank” function - it may contain only “while (1)” loop. The cost of this solution will be 4 bytes in each task’s stack. It can be optional and enabled by default for debug mode. The benefit of this solution is that you will not get HardFault exception which cannot be tracked by stack calls.

rtel wrote on Friday, September 13, 2013:

This is a good discussion with some good points being made.

Maybe there could be something done with configASSERT() - so you get an assertion if you drop out of a task.  Any overhead incurred would then only be while configASSERT() was defined.  The problem with that is your stack usage would then change depending on if configASSERT() was defined or not.

Another alternative would be to start changing port layers as they are worked on - so gradually over time the newer and more popular ports would get new functionality added, but the older ports would never get the behaviour change.  The down side of that would be the documentation would become confusing as the behaviour would depend on the port.