Pthread program hangs before pthread_join executes, can't figure out why

I'm trying to do an exercise with pthreads doing a fairly simple search where I divide a text file into 5 columns and 5 threads each perform a search. After this happens, then a merge occurs to decide if an input matches any of the individual entries from the text file. However, when I run it, it seems to hang. I think I have a race condition of some variety, but debugging with DDD has not yielded anything yet.

I think that I'm doing the pthread creation and joining correctly but I'm not really sure if I'm using the mutexes right.

The search function creates a linked list of unique values in a given column and then creates a bitmask that holds the indicies where that value is found. Anyway, if I run a standard linear search, I get 7 more results for my test data than if I do it threaded, which I take to mean that something is failing in the search or merge thread. Reducing the batch size from 10% chunks of my dataset to 1 or 2 values at a time increases the number of matches, but I still miss the correct total by a couple.

If anybody has ideas as to why the program hangs (probably due to the search or merge threads) before completion, I'd appreciate the help.

I've omitted about half the code for brevity's sake, but I can post more if it would be helpful.

void * search(void* pthread_arg){
  search_thread_param * myParams = (search_thread_param*) pthread_arg;
  int k=0; // how many searches have been done so far
  int m;
  while (k<NUM_PACKETS){
    pthread_mutex_lock(&mutex);
    if(n !=0){
      pthread_cond_wait(&search_cv, &mutex);  // mege is in progress, go to sleep
    }
    pthread_mutex_unlock(&mutex);     // release th lock so the other search threads can acquire it

    for (m =0; m < BATCH; m++)
      myParams->buffer[m] = mySearchFunction(myParams->packet_field[k+m], myParams->rule_field, unique_no[myParams->thread_id]);  // given a value, return its BV

    k=k+m;
    pthread_mutex_lock(&mutex);
    if (n==NUM_FIELDS-1) // this search thread is the only active one
      {
    n++;

    pthread_mutex_unlock(&mutex);   
    pthread_cond_signal(&merge_cv); // wake up merge thread
      } 
    else{  // not the last one goes to sleep
      n++;
      pthread_mutex_unlock(&mutex); 
    }   
  } 
  return NULL;
}

void merge_function(unsigned long b0,unsigned long b1,unsigned long b2,unsigned long b3,unsigned long b4){
  unsigned long final_BV;

  final_BV = b0 & b1 & b2 & b3 & b4;

  if( final_BV )
  int counter = 0;
    while(final_BV){
      counter++;
      final_BV = final_BV >> 1; //bit shift 
    }
    if( counter)
      printf("matched rule %i\n", counter);

}
void * merge (void* pthread_arg){
  merge_thread_param * myParams = (merge_thread_param*) pthread_arg;
  int k=0; // how many merges have been done so far
  int m;

  pthread_mutex_lock(&mutex);
  if (n<NUM_FIELDS) // the first batch is not ready
    pthread_cond_wait(&merge_cv, &mutex);    // go to sleep

  while (k<NUM_PACKETS){
    for (m =0; m < BATCH; m++){
      merge_function(myParams->buffer[0][m],myParams->buffer[1][m],myParams->buffer[2][m],myParams->buffer[3][m],myParams->buffer[4][m]);
    }
      printf("Merge thread: finish merging one batch\n");   
      k=k+m;
      n = 0; //ready to wake up all search threads
      if(k ==NUM_PACKETS){  // the program is over
    pthread_mutex_unlock(&mutex);   
    printf("Merge thread:  I am done, found %i results, compared to %i linear search  n = %i\n",res,lin,n);
    return NULL;
      }
      else  {
    pthread_cond_broadcast(&search_cv);
    pthread_mutex_unlock(&mutex);
    pthread_cond_wait(&merge_cv, &mutex);    // go to sleep
      }  
  }     
  return NULL;
}

int main () {
///////setup info omitted for brevity
  // create search threads
  for (i=0; i< NUM_FIELDS; i++)
    if(pthread_create(&s_thread[i], &attr, search, (void*) &stp[i])!=0){printf("Creating Thread failed!\n");}

  // create merge thread        
  if(pthread_create(&m_thread, &attr, merge, (void*) &mtp)!=0){printf("Creating Thread failed!\n");}

  // join the threads
    for (i=0; i<NUM_FIELDS; i++)
    if (pthread_join(s_thread[i], NULL)==0){printf("joined thread %i\n",i);}
    else{printf("Joining thread %i failed!\n",i);}

  if (pthread_join(m_thread, NULL)!=0){printf("joined merge thread");}
  else{printf("Joining thread failed!\n");}     

  pthread_attr_destroy(&attr);
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&search_cv);
  pthread_cond_destroy(&merge_cv);      
  //free dat memory
  printf("finished joining all the threads");
  fflush(stdout);
  return 0;
}

Answers


It turns out the issue was that check to decide whether or not to set the pthread_cond_wait in the merge thread was faulty, causing the merge thread to execute before the search thread. This means that the merge thread finished before the search thread finished generating results. The search thread then signaled a non-existent thread and went to sleep. It never joined because it never completed. So, there you have it.


Need Your Help

PHP: How to get <br/> working in a simplexml_load_file() var

php xml simplexml

I am loading an xml in php via simplexml_load_file().

Create hyperlink in django template of object that has a space

html django templates hyperlink

I am trying to create a dynamic hyperlink that depends on a value passed from a function: