Menu ▾ ▴

#197 FreeRTOS+POSIX possible race condition in pthread_cond_timedwait

v1.0 (example)
closed-fixed
nobody
posix (1)
5
2020-02-21
2019-08-14
No

Greetings,

I downloaded FreeRTOS+POSIX from labs on Monday 14-Aug-2019
        version Amazon FreeRTOS+POSIX V1.0.0
and from reviewing the code I believe I may have found a race condition in the function pthread_cond_timedwait() that corrupts the state of the pthread_cond_t.

The race occurs at line 232 in the file FREERTOS_POSIX_pthead_cond.c in the else block that deals with having timed out while waiting for the condition. Here is the relevant code :

209  /* Increase the counter of threads blocking on condition variable, then
210   * unlock mutex. */
211    if( iStatus == 0 )
212    {
213       ( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondMutex, portMAX_DELAY );
214       pxCond->iWaitingThreads++;
215       ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
216
217       iStatus = pthread_mutex_unlock( mutex );
218    }
219
220    /* Wait on the condition variable. */
221    if( iStatus == 0 )
222    {
223       if( xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondWaitSemaphore,
224                            xDelay ) == pdPASS )
225       {
226           /* When successful, relock mutex. */
227          iStatus = pthread_mutex_lock( mutex );
228       }
229       else
230       {
231           /* Timeout. Relock mutex and decrement number of waiting threads. */
232           iStatus = ETIMEDOUT;
233           ( void ) pthread_mutex_lock( mutex );
234
235           ( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxCond->xCondMutex, portMAX_DELAY );
236           pxCond->iWaitingThreads--;
237           ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxCond->xCondMutex );
238       }
239   }

Here is the scenario I think is problematic:

1. Thread 1 calls pthread_cond_wait() and on line 214 increments pxCond->iWaitingThreads to 1. 2. Thread 1 unlocks his client mutex on line 217 3. Thread 1 attempts to take the counting semaphore representing the condition on line 223 but times out, arriving at line 232. 4. Before Thread 1 can re-aquire his client mutex on line 233, Thread 2 locks the client mutex and calls pthread_cond_signal(). 5. Thread 2, in pthread_cond_signal(), sees that pxCond->iWaitingThreads is >0, gives the counting semaphore and decrements pxCond->iWaitingThreads to 0 6. Thread 2 exits from pthread_cond_signal() and releases the client mutex allowing Thread 1 to arrive at line 233 and acquire the mutex. 7. Thread 1 arrives at line 236 and decrements pxCond->iWaitingThreads to -1, corrupting the internal state of the pthread_cond_t

Discussion

  • Don Woodward

    Don Woodward - 2019-11-14

    Hello... I just ran into this bug today. So I'm confirming the race condition exists..

     
  • Richard Barry

    Richard Barry - 2020-02-21
    • status: open --> closed-fixed
     

Log in to post a comment.