From 42135c1a22d0d5f902eac2da027ed5c43e4ae1c7 Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Sat, 25 Jan 2025 10:26:19 +0000 Subject: [PATCH] Mark mutex as robust to prevent deadlocks Prevent application hangs that occur when a thread dies while holding a mutex, particularly during vTaskEndScheduler or exit calls. This is achieved by setting the PTHREAD_MUTEX_ROBUST attribute on the mutex. Fixes: - GitHub issue: FreeRTOS/FreeRTOS-Kernel#1217 - Forum thread: freertos.org/t/22287 Signed-off-by: Gaurav Aggarwal --- .../GCC/Posix/utils/wait_for_event.c | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c b/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c index bf744e27f..443bb7909 100644 --- a/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c +++ b/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c @@ -35,6 +35,7 @@ struct event { pthread_mutex_t mutex; + pthread_mutexattr_t mutexattr; pthread_cond_t cond; bool event_triggered; }; @@ -46,7 +47,9 @@ struct event * event_create( void ) if( ev != NULL ) { ev->event_triggered = false; - pthread_mutex_init( &ev->mutex, NULL ); + pthread_mutexattr_init( &ev->mutexattr ); + pthread_mutexattr_setrobust( &ev->mutexattr, PTHREAD_MUTEX_ROBUST ); + pthread_mutex_init( &ev->mutex, &ev->mutexattr ); pthread_cond_init( &ev->cond, NULL ); } @@ -56,13 +59,18 @@ struct event * event_create( void ) void event_delete( struct event * ev ) { pthread_mutex_destroy( &ev->mutex ); + pthread_mutexattr_destroy( &ev->mutexattr ); pthread_cond_destroy( &ev->cond ); free( ev ); } bool event_wait( struct event * ev ) { - pthread_mutex_lock( &ev->mutex ); + if( pthread_mutex_lock( &ev->mutex ) == EOWNERDEAD ) + { + /* If the thread owning the mutex died, make the mutex consistent. */ + pthread_mutex_consistent( &ev->mutex ); + } while( ev->event_triggered == false ) { @@ -82,7 +90,11 @@ bool event_wait_timed( struct event * ev, clock_gettime( CLOCK_REALTIME, &ts ); ts.tv_sec += ms / 1000; ts.tv_nsec += ( ( ms % 1000 ) * 1000000 ); - pthread_mutex_lock( &ev->mutex ); + if( pthread_mutex_lock( &ev->mutex ) == EOWNERDEAD ) + { + /* If the thread owning the mutex died, make the mutex consistent. */ + pthread_mutex_consistent( &ev->mutex ); + } while( ( ev->event_triggered == false ) && ( ret == 0 ) ) { @@ -101,7 +113,11 @@ bool event_wait_timed( struct event * ev, void event_signal( struct event * ev ) { - pthread_mutex_lock( &ev->mutex ); + if( pthread_mutex_lock( &ev->mutex ) == EOWNERDEAD ) + { + /* If the thread owning the mutex died, make the mutex consistent. */ + pthread_mutex_consistent( &ev->mutex ); + } ev->event_triggered = true; pthread_cond_signal( &ev->cond ); pthread_mutex_unlock( &ev->mutex );