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 <aggarg@amazon.com>
---------
Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c
index dd7ca1a..b5a4a1b 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 @@
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 );