-1

I am writing a code wherein I am making my threads wait till I do a pthread_cond_broadcast. I have three threads in this code. Threads line2_thread and line3_thread, are running in the order of their priority like they are supposed to run. However, my third thread doesn't even enter its thread function (line4_thread). Can anyone tell me why is my main() not being able to call my line4_thread ? pthread_cond_t sstart; pthread_mutex_t sstart_mutex;

void *l3_thread(void *arg){

pthread_mutex_lock(&sstart_mutex);
pthread_cond_wait(&sstart, &sstart_mutex);
pthread_mutex_unlock(&sstart_mutex);
/*do something*/

pthread_exit(NULL);

}

void *l2_thread(void *arg){

pthread_mutex_lock(&sstart_mutex);
pthread_cond_wait(&sstart, &sstart_mutex);
pthread_mutex_unlock(&sstart_mutex);
/*do something*/

pthread_exit(NULL);

}


void *l4_thread(void *arg){

pthread_mutex_lock(&sstart_mutex);
pthread_cond_wait(&sstart, &sstart_mutex);
pthread_mutex_unlock(&sstart_mutex);
/*do something*/

pthread_exit(NULL);

}

int main(){

pthread_cond_init(&sstart, NULL);

//thread creation

pthread_cond_broadcast(&sstart);
pthread_cond_destroy(&sstart);
    pthread_mutex_destroy(&sstart_mutex);

return 0;
}
Moose
  • 751
  • 22
  • 42
  • can you show attr_for_line4 declaration and how it is set? – Garr Godfrey Sep 16 '18 at 01:59
  • also, your join...is it possible main is exiting before line4 has a chance to run? – Garr Godfrey Sep 16 '18 at 02:03
  • pthread_t line4; pthread_attr_t attr_for_line4; int prio_line4 = 30; struct sched_param p_line4; pthread_attr_init (&attr_for_line4); temp_line4 = pthread_attr_getschedparam (&attr_for_line4, &p_line4); p_line4.sched_priority = prio_line4; pthread_attr_setschedparam (&attr_for_line4, &p_line4); pthread_attr_setschedpolicy(&attr_for_line4, SCHED_FIFO); – Moose Sep 16 '18 at 02:04
  • even if I call line4_thread before other two, it doesnt enter the function only. – Moose Sep 16 '18 at 02:05
  • Assuming that `pthread_join` was called, it might be locked in the mutex before it gets in to the `/* do something */` area – LWimsey Sep 16 '18 at 02:55
  • even If i print someting inside line4_thread before I lock mutex, it still doesnt print it. – Moose Sep 16 '18 at 03:00
  • In that case, did you call `pthread_join` for each thread (3 times) ? – LWimsey Sep 16 '18 at 03:01
  • yes I did call pthread_join. – Moose Sep 16 '18 at 03:02
  • In your code, there are a few shortcuts. If you edit the question to include the code that actually triggers the problem, it should be easy enough to find it – LWimsey Sep 16 '18 at 03:06
  • Can you check it now please ? – Moose Sep 16 '18 at 03:16
  • It does enter each thread.. The only problem I see is that pthread_cond_broadcast` is probably missed by the threads so that they are locked in the mutex forever.. – LWimsey Sep 16 '18 at 03:26
  • every time I run this code, line2 and line3 threads they execute. (All the time). Line4 doesnt (Never). Is any concept at play here ? – Moose Sep 16 '18 at 03:27
  • But how do you know that ? I don't see any `printf` statements in your threads. When I add them, they print in each thread as expected. The only problem is that it hangs (after that), but there is an explanation for that – LWimsey Sep 16 '18 at 03:45
  • Printf sometimes for me gets printed as well. but trying printing after you unlock mutex in line4 thread. Then it becomes inconsistent. – Moose Sep 16 '18 at 04:28
  • 1
    Probably because you've hit a deadlock. [this question](https://stackoverflow.com/questions/30637187/avoiding-deadlock-when-pthread-cond-wait-and-pthread-cond-signal) contains more info – LWimsey Sep 16 '18 at 04:41
  • Your mutex doesn't actually protect anything. – David Schwartz Sep 20 '18 at 17:43
  • After answer below was posted and implemented, they do actually. – Moose Sep 25 '18 at 04:07

1 Answers1

3

I think you have a few problems here. With apologies (I'm on my phone so typing a long answer is hard) I'm just going to focus on a couple things, since it's not 100% clear to me what you're actually trying to do.

When all your threads start they all try to acquire the mutex, and only one succeeds. Probably l3 but I don't think that's guaranteed here. It then calls the pthread_cond_wait and unlocks the mutex allowing one of the other threads to reach its pthread_cond_wait. But in the meantime. You've allowed your main thread to call pthread_cond_broadcast, and you've taken no steps to synchronize this with the other threads. It may happen before the others get unblocked from waiting for the mutex, and before their wait call, so they could miss the signal and block forever.

Further, I think it's a bit sketchy to immediately call pthread_cond_destroy. Like I said there's no synchronization between your main thread and your worker threads, so it's possible you could call pthread_cond_broadcast followed by pthread_cond_destroy, so some of your threads might be calling pthread_cond_wait on an invalid condition variable and deadlock.

Check the return values of pthread_cond_wait. If I'm right, it might return EINVAL in some cases. But I haven't tested this so there might be a flaw in my reasoning.

Iguananaut
  • 21,810
  • 5
  • 50
  • 63
  • Good answer... Destroying the condition variable while others are still using it probably engenders undefined behavior. I would not assume that it might deadlock or return `EINVAL` – LWimsey Sep 16 '18 at 18:26
  • That is explanatory. I tried destroying Conditional wait after 10 secs. I want my code to run for 10 secs and want them to execute in the order of their priority. After 10 seconds, two threads finish executing and I still dont see l4 thread executing (lowest priority). – Moose Sep 16 '18 at 18:56
  • 1
    There's no point in destroying the conditional until after the threads are completely done running (e.g. after all the join calls). Meanwhile, you have other problems. Like I wrote, you have no synchronization between your main thread and the worker threads, so for example you have not designed things in such a way that you can guarantee that the `pthread_cond_broadcast` will reach all threads at the same time--that is, that they're all blocked at the condition wait by the time you broadcast. – Iguananaut Sep 17 '18 at 14:39
  • When I do cond broadcast, l2 thread releases the mutes and then l3 hold is til it releases it. Since l3 is also running, doesnt it imply that it has released mutex for l4 to acquire ? Because /*do something*/ for l2 and l3 are completing. I am badically confused on this path ? – Moose Sep 17 '18 at 16:54
  • Moreover, I think I can fix this but is my understanding about flow of the code correct in my comment above this? – Moose Sep 17 '18 at 17:01
  • In theory yes, but simultaneously to that the main thread is still running and calling broadcast, possibly before all threads have even released the mutex. This is why I say you need some mechanism to ensure that main thread is synchronized so that all threads are waiting before you try to wake them with a broadcast. – Iguananaut Sep 18 '18 at 09:33
  • Makes sense now. I fixed this by broadcasting for thread with medium priority from thread with highest priority, and so on so forth. My main only broadcasts for my l3 thread now. Read a post about this being called predicating. – Moose Sep 19 '18 at 15:43
  • You're on the right track. Make sure also your main thread holds the mutex before broadcasting. – Iguananaut Sep 20 '18 at 07:18
  • Done. Thanks a lot for your time and inputs on this one. – Moose Sep 20 '18 at 16:12