fix(POSIX port): check pthread_key_create/pthread_setspecific return values

prvInitThreadKey() ignored pthread_key_create()'s return value, and
prvMarkAsFreeRTOSThread() ignored pthread_setspecific()'s return
value.

If pthread_setspecific() fails, the one-byte thread marker allocated
just before it is neither stored in TLS (so prvThreadKeyDestructor()
never runs for it, leaking the allocation) nor freed locally -- and
the thread is left unmarked, so prvIsFreeRTOSThread() silently
misclassifies it as not a FreeRTOS thread. The correctness impact
(thread identity) is larger than the one-byte leak itself.

Fix: check both return values. On pthread_setspecific() failure, free
the marker to avoid the leak, then call prvFatalError() -- the same
handling this port already uses for other unexpected pthread call
failures (pthread_create(), sigaction()). This function returns void,
so there is no way to propagate a failure to the caller; continuing
past a failed pthread_setspecific() would leave the thread silently
misclassified rather than failing loudly. Same treatment for
pthread_key_create(), since a failure there means every later
pthread_setspecific()/pthread_getspecific() call on xThreadKey is
operating on an invalid key.

Fixes #1447

Signed-off-by: Saikumar Mandaji <mandajisaikumar@gmail.com>
This commit is contained in:
Saikumar Mandaji 2026-07-18 19:20:34 +05:30
parent 78069a79ea
commit ccbd282d5c

View file

@ -139,7 +139,15 @@ static void prvThreadKeyDestructor( void * pvData )
static void prvInitThreadKey( void )
{
pthread_key_create( &xThreadKey, prvThreadKeyDestructor );
int iRet;
iRet = pthread_key_create( &xThreadKey, prvThreadKeyDestructor );
if( iRet != 0 )
{
prvFatalError( "pthread_key_create", iRet );
}
/* Destroy xThreadKey when the process exits. */
atexit( prvDestroyThreadKey );
}
@ -148,6 +156,7 @@ static void prvInitThreadKey( void )
static void prvMarkAsFreeRTOSThread( void )
{
uint8_t * pucThreadData = NULL;
int iRet;
( void ) pthread_once( &hThreadKeyOnce, prvInitThreadKey );
@ -156,7 +165,21 @@ static void prvMarkAsFreeRTOSThread( void )
*pucThreadData = 1;
pthread_setspecific( xThreadKey, pucThreadData );
iRet = pthread_setspecific( xThreadKey, pucThreadData );
if( iRet != 0 )
{
/* The marker was not stored, so the TLS destructor would never run
* for it -- free it here instead of leaking it, then treat the
* failure as fatal via prvFatalError(), consistent with how this
* port already handles other unexpected pthread call failures
* (see pthread_create()/sigaction() above). This function returns
* void, so there is no way to propagate the failure to the caller;
* continuing would leave the thread unmarked and silently
* misclassified by prvIsFreeRTOSThread(). */
free( pucThreadData );
prvFatalError( "pthread_setspecific", iRet );
}
}
/*-----------------------------------------------------------*/