c++ - pthread_cond_wait sometimes will not receive the signal -


i have weird problem pthread_cond_wait , pthread_cond_signal. have arranged series of threads. in sleep state when started. wake function signal these threads, work, , wait results.

in setup below, td thread data, containing mutex , conditions, , th array containing pointer threads:

for (size_t = 0; < num_threads; i++) {     pthread_cond_init(&td[i].cond, null);     pthread_mutex_init(&td[i].cond_mutex, null);     pthread_mutex_init(&td[i].work_mutex, null);     pthread_mutex_lock(&td[i].cond_mutex);     pthread_mutex_lock(&td[i].work_mutex);     pthread_create(&th[i], null, thread_worker, (void *)&td[i]); } 

thread worker this:

void* thread_worker(void* data) {     thread_data *td = (thread_data *)data;     while (1) {         pthread_cond_wait(&td->cond, &td->cond_mutex);  // marker          // work ...          pthread_mutex_unlock(&td->work_mutex);     }     pthread_exit(null); } 

this job function supposed wake threads, job, , wait them finish:

void job() {     (size_t = 0; < num_threads; i++) {         pthread_cond_signal(&td[i].cond);     }     (size_t = 0; < num_threads; i++) {         pthread_mutex_lock(&td[i].work_mutex);  // block until work done     } } 

in rare situations (1 out of 1000 runs maybe), above setup encounter freeze. when happens, 'marker' line in thread_worker not signaled pthread_cond_signal, kept on waiting. it's rare happens time time. i've produced numerous log messages, , verified pthread_cond_wait called before pthread_cond_signal. doing wrong here?

there nothing there forces pthread_cond_wait() called before pthread_cond_signal(). despite logging, it's entirely possible logged lines out-of-sequence happened.

you aren't using mutexes , condition variables correctly: mutexes should unlocked same thread locked them, , condition variables should paired test on shared state (called predicate). shared state supposed protected mutex passed pthread_cond_wait().

for example, example can reworked correctly use mutexes , condition variables. first, add int work_status thread_data structure, 0 indicates thread waiting work, 1 indicates work available , 2 indicates work complete.

you don't appear need 2 mutexes in each thread_data, , don't want lock mutex in main thread when you're setting up:

for (size_t = 0; < num_threads; i++) {     pthread_cond_init(&td[i].cond, null);     pthread_mutex_init(&td[i].cond_mutex, null);     td[i].work_status = 0;     pthread_create(&th[i], null, thread_worker, (void *)&td[i]); } 

have threads wait on work_status using condition variable:

void* thread_worker(void* data) {     thread_data *td = (thread_data *)data;      while (1) {         /* wait work available */         pthread_mutex_lock(&td->cond_mutex);         while (td->work_status != 1)             pthread_cond_wait(&td->cond, &td->cond_mutex);         pthread_mutex_unlock(&td->cond_mutex);          // work ...          /* tell main thread work has finished */         pthread_mutex_lock(&td->cond_mutex);         td->work_status = 2;         pthread_cond_signal(&td->cond);         pthread_mutex_unlock(&td->cond_mutex);     }     pthread_exit(null); } 

...and set , wait on work_status appropriate in job():

void job() {     /* tell threads work available */     (size_t = 0; < num_threads; i++) {         pthread_mutex_lock(&td[i].cond_mutex);         td[i].work_status = 1;         pthread_cond_signal(&td[i].cond);         pthread_mutex_unlock(&td[i].cond_mutex);     }      /* wait threads signal work complete */     (size_t = 0; < num_threads; i++) {         pthread_mutex_lock(&td[i].cond_mutex);         while (td[i].work_status != 2)             pthread_cond_wait(&td[i].cond, &td[i].cond_mutex);         pthread_mutex_unlock(&td[i].cond_mutex);     } } 

Comments