views:

58

answers:

2

I seem to be running in to a possible deadlock with a pthreads conditional variable.

Here is the code

thread function(){
    for (condition){
        do work
        /* should the thread continue? */
        if (exit == 1){
            break; /* exit for */
        } 
     } /* end for */

pthread_mutex_lock(&mtxExit);
exit = 0;
pthread_cond_signal(&condVar);
pthread_mutex_unlock(&mtxExit);
}

The main function is as follows:

function main(){
    if (thread is still active){
          pthread_mutex_lock(&mtxExit);
          exit = 1;
          pthread_mutex_unlock(&mtxExit);
          } /* end if */
    while (exit == 1){
       pthread_mutex_lock(&mtxExit);
       /* check again */
       if (exit == 1)
           pthread_cond_wait(&condVar, &mtxExit);
       pthread_mutex_unlock(&mtxExit);
       }
    create new thread()
    ....
    }

The code is always getting stuck at cond_wait. :(

EDIT:

Let me add some clarification to the thread to explain what I am doing.

At any given time, I need only one thread running. I have a function that starts the thread, tells it what to do and the main thread continues it work.

The next time the main thread decides it needs to spawn another thread, it has to make sure the thread that was previously started has exited. I cannot have two threads alive at the same time as they will interfere with each other. This is by design and by definition of the problem I am working on.

That is where I am running in to problems.

This is my approach:

Start the thread, let it do its job.

the thread checks in every step of its job to see if it is still relevant. This is where "exit" comes in to picture. The main thread sets "exit" to 1, if it needs to tell the thread that it is no longer relevant.

In most cases, the thread will exit before the main thread decides to spawn another thread. But I still need to factor in the case that the thread is still alive by the time the main thread is ready to start another one.

So the main thread sets the value of "exit" and needs to wait for the thread to exit. I dont want to use pthread_kill with 0 as signal because then main thread will be in a loop wasting CPU cycles. I need the main thread to relinquish control and sleep/wait till the thread exits.

Since I only need one thread at a time, I dont need to worry about scaling to more threads. The solution will never have more than one thread. I just need a reliable mechanism to test if my thread is still alive, if it is, signal it to exit, wait for it to exit and start the next one.

From my testing, it looks like, the main thread is still entering the conditional variable even if the thread may have exited or that the signal is not getting delivered to the main thread at all. And its waiting there forever. And is some cases, in debugger I see that the value of exit is set to 0 and still the main thread is waiting at signal. There seems to be a race condition some where.

I am not a fan of how I set up the code right now, its too messy. Its only a proof of concept right now, I will move to a better solution soon. My challenge is to reliably signal the thread to exit, wait on it to exit.

I appreciate your time.

+3  A: 

Did you forget to initialize your condition variable?

pthread_cond_init(&condVar, NULL)
Dennis Miller
I used static initialization PTHREAD_COND_INITIALIZER
powerrox
My conditional var is also declared a global var since I dont have more than one thread active at a time.
powerrox
A: 

while (exit == 1) {

In the code you quote, the way you quote I do not see any particular problem. It is not clean, but it appears functional. What leads me to believe that somewhere else you are setting exit to 0 without signaling that. Or the thread is getting stuck somewhere doing the work.

But considering the comments which hint that you try to signal one thread to terminate before starting another thread, I think you are doing it wrong. Generally pthread condition signaling shouldn't be relied upon if a signal may not be missed. Though it seems that state variable exit covers that, it is still IMO wrong application of the pthread conditions.

In the case you can try to use a semaphores. While terminating, the thread increments the termination semaphore so that main can wait (decrement) the semaphore.

thread function()
{
   for (condition)
   {
      do work
      /* should the thread continue? */
      if (exit == 1) {
         break; /* exit for */
      } 
   } /* end for */
   sem_post(&termSema);
}

function main()
{
    if (thread is still active)
    {
          exit = 1;
          sem_wait(&termSema);
          exit = 0;
    }
    create new thread()
    ....
}

As a general remark, I can suggest to look for some thread pool implementations. Because using a state variable to sync threads is still wrong and doesn't scale to more than one thread. And error prone.

Dummy00001
Please see my edit above.
powerrox
@powerrox: semaphore advise stands, even with the new comment. If thread finishes, the sema is already incremented and main wouldn't wait. If thread is still running main would block on decrement - waiting for thread to increment the semaphore.
Dummy00001