LeakSanitizer detects memory leaks occasionally in GCC/Posix

I’m trying to make some unit tests that include FreeRTOS functionality, and the very simplest thing I could think of (make a thread, return) sometimes causes the process to return a non-zero status code. This is what the error message looks like:

==280233==ERROR: LeakSanitizer: detected memory leaks
 
Direct leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x5670748f in malloc (/home/nathan/blah/rtos_test_repro_c+0xdb48f) (BuildId: b8c04741b4691b0b82a3fec5931e4cc0bd8a3ad4)
    #1 0x5676efcd in prvMarkAsFreeRTOSThread /home/nathan/blah/lib/freertos/portable/ThirdParty/GCC/Posix/port.c:152
 
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).

It doesn’t happen all the time, but if I run it in a loop for a while, it happens reliably.

I’m using FreeRTOS 11.2.0. I’d upload my FreeRTOSConfig.h and the source code, but new users can’t upload attachments. The code is small, though, so here’s the source code. The only big thing about the config that’s different from the example is that I turned off dynamic memory.

#include <FreeRTOS.h>
#include <task.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>

static StackType_t stack[4096];
static StaticTask_t task;

static void callback(void *unused)
{
    (void)unused;
    vTaskEndScheduler();
    while (true);
}

void test_setup_threads(void)
{
    xTaskCreateStatic(callback, "thread", 4096, NULL,
                      FREERTOS_PRIORITY_NORMAL, stack, &task);
    vTaskStartScheduler();
}

void vAssertCalled(const char *const pcFileName, unsigned long ulLine)
{
    fprintf(stderr, "Assertion at %s:%lu\n", pcFileName, ulLine);
    while(true);
}

void vApplicationIdleHook(void)
{
}

void vApplicationStackOverflowHook(TaskHandle_t taskp, char *task_name)
{
    (void)taskp;
    (void)task_name;
}

Oh, and because it’s obviously relevant, I’m compiling and linking with -fsanitize=undefined -fsanitize=address -fno-sanitize-recover -static-libasan

Would you please share the complete project that I can use to repro the issue?

You should now be able to upload.

Sure, here are the files involved:

test_repro.c (750 Bytes)
FreeRTOSConfig.h (3.5 KB)

and the command to build it:

$ gcc -I../../../lib/freertos/include -I../../../lib/freertos/portable/ThirdParty/GCC/Posix/utils -I../../../lib/freertos/portable/ThirdParty/GCC/Posix -I../include/test/ -m32 -Wall -Wextra -Wshadow -Werror -O2 -g3 -fsanitize=undefined -fsanitize=address -fno-sanitize-recover -static-libasan -fomit-frame-pointer -o test_thread test_repro.c ../../../lib/freertos/*.c ../../../lib/freertos/portable/ThirdParty/GCC/Posix/*.c ../../../lib/freertos/portable/ThirdParty/GCC/Posix/utils/*.c

Replace the path to the FreeRTOS sources where appropriate to make it work for you. Given that executable, I then just run:

$ while true ; do ./test_thread || break ; done
 
=================================================================
==23290==ERROR: LeakSanitizer: detected memory leaks
 
Direct leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x5668f58f in malloc (/home/nathan/repos/qlx300_fw/modules/rtos/test/test_thread+0xe358f) (BuildId: 42003c56e4a8fd15e2ab30f87b61f26ede21df44)
    #1 0x5670b29d in prvMarkAsFreeRTOSThread ../../../lib/freertos/portable/ThirdParty/GCC/Posix/port.c:152
 
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).

I just tried it 3 times, and it took 7, 17, and 5 seconds on my system to hit the issue.

I’ve tested with GCC 14.2.0-19 and Clang 19.1.7, with the same results.

I imagine the issue is that the call to vTaskEndScheduler does not signal the destruction of the thread. Related issue from 2021 vTaskEndScheduler for testing. I will take a deeper look.