How do I check on the state of a task? (How do I know when it has been deleted?)

I’m trying to get to grips with rtos and I can’t seem to figure out how one might go about checking whether or not a task has been deleted.

Searching around, I stumbled upon “eTaskGetState”, however that returns data which has me confused.

Here is a quick snippet demonstrating what I mean/where I am confused

if (command.equals("on"))
{
    xTaskCreate(
        task_Alarm_Func,     /* Task function. */
        "Alarm Function",    /* name of task. */
        STACK_SIZE,          /* Stack size of task in bytes (Usually words, but esp32 changes this)*/
        NULL,                /* parameter of the task */
        1,                   /* priority of the task */
        &task_Alarm_Handle); /* Task handle to keep track of created task */
}
else if (command.equals("off"))
{
    if (task_Alarm_Handle != NULL)
    {
    vTaskDelete(task_Alarm_Handle);
    }
}
else if (command.equals("test"))
{
    Serial.printf("\nTask State:\n%d\n", eTaskGetState(task_Alarm_Handle));
}

The numbers received when the task is running seem to make sense with my understanding of what’s happening, however, after the task has been deleted, it indicates that the deleted task is ready…

This is not what I was expecting and I’m not quite sure how I can go about checking whether or not a task is deleted.

I have also read that it is reasonable to make task handles null after deletion, however that doesn’t really work or would be very cumbersome whenever a task deleted itself I would imagine. That is why I have left it out of the snippet for testing purposes.

If its of any help, just some background information: Im currently using a TTGO T-Display (ESPRESSIF-ESP32 240MHz Xtensa® single-/dual-core 32-bit LX6) with Platform IO on VS Code and the Arduino Serial Monitor for read/writes to Serial. The FreeRTOS version is “V8.2.0”

I also have included some delay outside of the snippet (which is happening in loop, which I think runs in idle anyways) which I think means that there should be enough time for idle to run cleanup tasks

In case you really need to track deleted tasks (why ?) you have to do it on your own. It makes not much sense for an OS to keep an ever increasing list of deleted and free’d resources like tasks.
It’s similar to the heap with malloc and free. There is also no list of already free’d memory blocks in the normal implementation.
There are heap corruption/memory leak detector libraries wrapped around the base implemenation to do this kind of tracking. But this is for debugging only because it usually requires a lot of additional resources.

I don’t want to track them so much as I just want to know whether or not a task is deleted.

It seems you can get which of the 4 basic steps any task is in given its handle, but I can’t seem to find a way to detect whether or not it has been deleted, particularly if it has deleted itself.

This has given me some pause for thought, as in maybe you do get what I’m asking but maybe I misunderstood the complexity in/problem with what i’m actually asking for.

Based on what you have just said, I think I have a new understanding of what is going on perhaps. I think it just clicked what task deletion actual means.

So if I’m getting this correctly, when a task is deleted, its memory is freed up, and therefore any information that I was getting with eTaskGetState at that point, was merely junk data, waiting to be overwritten in the newly freed section of memory.

If that is the case, then what you are saying I think makes total sense, and the analogy to malloc also makes sense.

Assuming you are saying this is all correct, how then would one track the status of a task traditionally? I assume the task in question could set some sort of flag which alerted you to its status before deleting itself or any other sort of structures that would accomplish this goal?


Also, a totally minor aside, related to:

Could you not tell what blocks of memory were free by seeing what blocks were allocated? I still get what you mean, this is more a humorous smart aleck point that may or may not have an interesting answer for me.

Yes, you have to store a flag/the status yourself somewhere.

You’d have to keep a list all currently allocated blocks including their sizes.
That’s also not feasable for production code.

What I meant previously is, doesn’t the os or I guess whatever the analog for that is here with microcontrollers already keep a memory allocation table of what memory is allocated? This is getting off topic I know, but surely there, one could discern whether or not the block was allocated via the same mechanism that makes sure nothing else writes to that memory.

So sort of answering my own question with a brief googling, so what Im getting is that there isn’t a way to actually ask what part of memory is allocated in c, which seems really odd to me because something somewhere has to know what memory is allocated, and surely that thing, whatever it is, could fairly easily tell you by checking that table as it must do internally anyways. Seems like the only thing missing would be communication between the allocator and the user of that memory.

Regardless, that’s a puzzle for me to figure out on another day I guess, and you, I think, have answered my main question so I will mark this solved.

Thanks.

It’s basically a question of the actual heap implementation, which is not part of the OS but usually of the C-library.
And usually the common heap implementations don’t keep a table of allocated blocks because it’s not needed and it would be a huge overhead memory and performance wise (instead some have free list(s)) .
Have a look at the malloc implementation of e.g. newlib (C standard library for embedded/bare metal applications) if you’re interested in the gory details :slight_smile:

1 Like

The issue comes down to fact that once a task has been deleted (or memory block freed) that handle is no longer valid to even ask about it, and the memory that references might get used from some other purpose. In order to ask if a task has been deleted you would need to keep forever a list of every task that ever was, which costs resources.

You could potentially take a task handle and scan the list of all tasks to see if the handle is valid, but that doesn’t mean the task you are asking about hasn’t been deleted, it might have been deleted and a totally new task created with its control block at the same address, so not so useful a test.

The same for memory blocks, you could see if there is a memory block at that address allocated, but you can’t tell if it is still the one you thought you had.

A basic rule when deleting a resource is that you first need to make sure everyone who might use it know it is going away and that they stop using it. Only then can you delete it. Otherwise you run the risk of using something after it is gone. To make it so something can check the status of another thing even after it is gone, requires making that handle eternal, which is generally costly, you need to permanently reserve that handle value.

Hi,this is my advise:
if a task want to suicide(delete itself), the opration can diliver to the daemon task( timer task) with a timer pend call, and daemon task should be give a very high priority, so it can do the deletion right away,and then asign NULL to handle of the task to be delete after the delete in the daemon task.
then you can check at other place whether a task exist by checking the value of its handle, be NULL or not.