xQueueReceive blocking although Queue is being deleted

Please consider this test code here:

static QueueHandle_t queue;

static void pullTask(void* data) {

    while (true) {

        char buffer;
        printf("Pulling Q...\n");
        auto result = xQueueReceive(queue, &buffer, portMAX_DELAY);
        printf("Returned w/ result %d\n", result);
    }
}

void app_main() {

    queue = xQueueCreate(1024, 1);
    TaskHandle_t pullTaskHandle;
    xTaskCreate(pullTask, "pull task", 3000, 0, 10, &pullTaskHandle);

    for (int i = 0; i < 5; ++i) {
        xQueueSend(queue, "1", portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
    printf("Deleting Q...\n");
    vQueueDelete(queue);
    printf("Q is gone!\n");

    while (true) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

Although I delete the queue, the other task hangs in xQueueReceive forever. I would have expected the call to return with an appropriate error code (SHUTDOWN) when the queue goes down.

Is that really the way it is supposed to work in FreeRTOS?
If so, what’s my best option to work around this deficiency.

Since the app that is blocking on the Queue is actively referencing the Queue, and when it wakes up is going to check to see if the Queue has data for it, it can not be deleted at this moment.

A basic tenant of programming is your should not invalidate a resource by deleting it while other parts of the code think it is still valid.

Thus, before deleting the Queue, your program really needs to notify all the other parts of the program that this is going to happen, and make sure they have all gotten and processed this notification, before deleting the Queue.

I see, thank you. This brings me to the next question… what’s the best way of notifying then?

I could send a special queue pseudo-message that means “we’re shutting down, please exit the loop” or I could use a semaphore and a QueueSet ­– or use an event group and poll the queue and the event group (although that will introduce latency).

What’s the usual way of dealing with that in FreeRTOS?

It depends a lot on what you are doing. As I just mentioned in another thread, I rarely have tasks “end” or delete resources. If you are “Shutting Down”, why do you need to delete stuff? Either you mean going into hybernation, so when you wake up, everything would need to be created again, or the system is being shut off, and the system will totally reboot when turned back on.

1 Like

I commented on the other question with regards to why I want to delete task and deallocate their allocated (IPC and hardware) resources.

With regards to my original queue problem… do you think such a feature (unblocking the task by sending a special error code as return from xQueueReceive) could be implemented in FreeRTOS? I’d be surprised if I was the only one stumbling over that behavior.

You could send such a message, but that is an application level operation, not something that FreeRTOS would know what to do with. Trying to allow the OS to try to handle this sort of action adds a LOT of complexity to the OS, and FreeRTOS is optimized to be simple and efficient. Since I believe most applications won’t have this sort of issue, it would be bloat for a niche case.

As Richard mentioned you can unblock a task (waiting in a blocking call) with FreeRTOS - xTaskAbortDelay() RTOS API function reference documentation to avoid using special values or messages.

1 Like

Thanks both of you, this sounds pretty amazing and would totally do for my use case. Will test and report back.