0

In the following code execute_on_thread() will keep on printing ".", while the main function waits for a condition to be signaled from execute_on_thread using pthread_cond_timedwait. However, it is not timing out after the specified 20 second timeout, it just keeps printing ".", nothing else is happening.

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define SHOW_TECH_CMD_MAX_EXEC_TIME       5 //in secs 
pthread_mutex_t waitMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t waitCond = PTHREAD_COND_INITIALIZER;

void *execute_on_thread();
void *execute_on_thread()
{
  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  pthread_mutex_lock( &waitMutex );
  while(1)
  {
    printf(".");
  }
  pthread_cond_signal( &waitCond );
  pthread_mutex_unlock( &waitMutex );
  return (void *) 0;

}
int main( )
{
  pthread_t tid;
  struct timespec   ts;
  int error;
  clock_gettime(CLOCK_REALTIME, &ts);
  ts.tv_sec += 20; 
  pthread_create(&tid,NULL,execute_on_thread,NULL);
  pthread_mutex_lock(&waitMutex);
  error = pthread_cond_timedwait(&waitCond, &waitMutex,&ts);
  pthread_mutex_unlock(&waitMutex);
  printf("come here 1\n");
  if(error == ETIMEDOUT)
  {
    printf("come here 2\n");
    error = pthread_cancel(tid);
    if(error != 0)
    {
       printf("come here 3\n");
    }
  }
}
sonicwave
  • 5,952
  • 2
  • 33
  • 49
manimuthu m a
  • 61
  • 1
  • 9

1 Answers1

1

Have a look at the documentation for pthread_cond_wait:

Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.

So, before pthread_cond_wait returns, be it due to a signal arriving or timing out, it tries to lock the mutex. But - since execute_on_thread never releases the mutex once it has it (due to the while(1) loop), pthread_cond_wait will be stuck waiting on the mutex to be unlocked.

If you for instance change your execute_on_thread to temporarily unlock the mutex during each cycle, you should be able to get it to work. For instance:

void *execute_on_thread()
{
  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);   //Not necessary - this is the default state for new threads
  pthread_mutex_lock( &waitMutex );
  while(1)
  {
    printf(".\n");
    pthread_mutex_unlock(&waitMutex);
    usleep(100*1000);                 //So that the screen doesn't completely fill up with '.'s
    pthread_mutex_lock( &waitMutex );
  }
  pthread_cond_signal( &waitCond );
  pthread_mutex_unlock( &waitMutex );
  return (void *) 0;
}

Note though, that there are a couple of other things that could be improved in your program - such as adding a guard variable to your conditional wait (have a look at condition variable - why calling pthread_cond_signal() before calling pthread_cond_wait() is a logical error?), adding a cleanup handler to make sure the mutex is unlocked if the cancel request is handled by execute_on_thread when the mutex is locked and similar tweaks.

Community
  • 1
  • 1
sonicwave
  • 5,952
  • 2
  • 33
  • 49