From 03db672b8f45db24aa99f12051f7cf86746b9ed9 Mon Sep 17 00:00:00 2001 From: arctic-alpaca <67190338+arctic-alpaca@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:02:44 +0200 Subject: [PATCH] Fix race in POSIX port `vPortEndScheduler` (#1262) * Fix race in POSIX port `vPortEndScheduler` The `vPortEndScheduler` checks whether it's a FreeRTOS thread after signalling the scheduler thread to stop. This creates a race between the check and the destruction of the thread key. By moving the signal to the scheduler thread after the check, the race is prevented. * Code review suggestions Signed-off-by: Gaurav Aggarwal --------- Signed-off-by: Gaurav Aggarwal Co-authored-by: Gaurav Aggarwal --- portable/ThirdParty/GCC/Posix/port.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index dd7ca1a9a..b5a4a1b62 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -48,8 +48,8 @@ * stdio (printf() and friends) should be called from a single task * only or serialized with a FreeRTOS primitive such as a binary * semaphore or mutex. -* -* Note: When using LLDB (the default debugger on macOS) with this port, +* +* Note: When using LLDB (the default debugger on macOS) with this port, * suppress SIGUSR1 to prevent debugger interference. This can be * done by adding the following line to ~/.lldbinit: * `process handle SIGUSR1 -n true -p false -s false` @@ -324,17 +324,23 @@ BaseType_t xPortStartScheduler( void ) void vPortEndScheduler( void ) { Thread_t * pxCurrentThread; + BaseType_t xIsFreeRTOSThread; /* Stop the timer tick thread. */ xTimerTickThreadShouldRun = false; pthread_join( hTimerTickThread, NULL ); + /* Check whether the current thread is a FreeRTOS thread. + * This has to happen before the scheduler is signaled to exit + * its loop to prevent data races on the thread key. */ + xIsFreeRTOSThread = prvIsFreeRTOSThread(); + /* Signal the scheduler to exit its loop. */ xSchedulerEnd = pdTRUE; ( void ) pthread_kill( hMainThread, SIG_RESUME ); /* Waiting to be deleted here. */ - if( prvIsFreeRTOSThread() == pdTRUE ) + if( xIsFreeRTOSThread == pdTRUE ) { pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); event_wait( pxCurrentThread->ev );