Ankush
Ankush

Reputation: 1071

Can a race condition occur between mutex unlocking and returning from function

I've been learning about Multithreaded applications and in particular, about how a mutex can be used to prevent race conditions. However, while writing some code, I discovered a race condition (using the helgrind tool from valgrind) in my code, I believe that execution in one thread may be pausing after the unlock and before the return.

If we take the example code below, is a race condition possible in between the mutex unlock and the return statement? If so, how do we get around this problem? (short of requiring the caller to pass in some sort of buffer and returning a constant value like 0)

#include <pthread.h>

int x = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

doSomething()
{
    pthread_mutex_lock(&mutex);
    ++x;
    pthread_mutex_unlock(&mutex);
               /* <-- Race Condition? */
    return x;
}

void *t2()
{
    doSomething();
}

main()
{
    pthread_t thread;
    pthread_t_create(&thread, NULL);
    doSomething();
    pthread_join(thread, NULL);
    return 0;
}

NOTE: I understand that in the above example, returning 'x' is useless, as x is global. However, in a library where 'x' needs to be global for library functions, but can't be exposed to the user, the return value becomes important.

Upvotes: 4

Views: 1598

Answers (1)

user2357112
user2357112

Reputation: 280291

Here's the sequence of events in your current code:

  1. Unlock the lock.
  2. Read the shared x variable.
  3. Return the value you read.

The read of x is completely unprotected.

What you need to do is

  1. Read the shared x variable.
  2. Unlock the lock.
  3. Return the value you read.

so that the read is protected by the lock. To do that, store the value of x to an unshared (local) variable before unlocking the lock, and use that as the return value:

int retval = x;
pthread_mutex_unlock(&mutex);
return retval;

Upvotes: 11

Related Questions