How to terminate a task without waiting to finish?

I have a task that communicates with a module using serial port.
It sends some string commands and reads received response.

The response is read through a queue. It polls a status from the external module. When the response does not contain the desired result it repeats the command.
That continues until a timeout occurs. The timeout is around 5 minutes.

When the desired result found, it invokes a callback and task exits.
That means the time the task might last is unknown and can be last from a few seconds to 5 minutes.

Sometimes I want to terminate that process imediately without waiting to finish.

Would that be okay to delete the task and recreate it again?

While you can delete the task, you need to remember that deleting a task doesn’t “undo” anything the task is doing. If the task doing the deleting is at the same or higher priority to the task it is deleting, then that task could literally be ANYWHERE in its execution path, except inside a critical section. If the task doing the deleting is LOWER in priority, you at least know the task is blocked somewhere.

What might be better is to set a global flag to indicate you want the task to “abort”, and perhaps call vTaskAbortDelay on the task to end any blocking it is currently in. This lets the task stop its operation at a know stable point in its operation.

Although global flags will be a good solution, the problem here is that I want to imediately power down an external module by disabling its power supply to enter low power state.

After doing so, the task communicating with the module will hang because it will get no responses, until some timeout occurs. That timeout time might be up to a few minutes. And this is the reason I want to terminate that task and restarting again. The thread will no be able to wake up because it will no longer get any data in its queue. Unless I push random bytes into its queue to force it to wake up in order to see the global flag. But this sounds like a bad architecture.

“Immediately” doing things like that tends to cause problems, like you are seeing. If you are only trying to save power, send the flag to the task responsible for that device, and let IT power down the module.

As I said, using the abort delay on the task WILL wake it up on the queue reception and get a timeout return value, allowing it to see the flag and recover.

As long as you are not just using portMAX_DELAYs and ignoring the return value (the above is a reason you shouldn’t do that), you are ok. In fact, if you put a timeout on the queue reception to catch the problem, you don’t need to use the abort delay.

Using portMAX_DELAY and ignoring errors may be an “easy” answer, but rarely correct.