1

Hi I'm stuck with this problem and I can't figure out which is the best solution for that:

I have a process with some threads. All the threads have signal masked and only one (SignalHandler) that check if there are pending signals.

  while(!shouldEnd){
        if(!sigwait(&set, &signum)){
            if(signum == SIGINT){
                fprintf(stderr, "Ricevuto SIGINT\n");
            }
            else{
                //TODO
            }
        }
    }

Now I would like to terminate even other threads when it receive a SIGINT (for instance). How can I do it properly ? The main problem is that the others thread might be waiting on a condition variable or waiting in a accept() (for socket connections). I think would be a good thing put a variable like "shouldEnd" and set it to 1 when threads should stop working. Is that a good idea ? And what about the waiting one ? Mostly for the one waiting for a socket connection ?

Levenlol
  • 305
  • 5
  • 17

1 Answers1

1

So, first and foremost, we don't know what you're using for threads. You might consider using libBoost for this, as it will make your life easier with RAII style locks and whatnot.

Anyhow, only the elected thread of your process (typically main(), in most examples), will catch the signal, unless you've enabled signal masking. When you want the threads to shut down cleanly, you just need to:

  1. Wakeup the threads waiting on accept() by modifying your FD set to include a pipe that can also wake up the blocking call.
  2. Simply signal the condvars the other threads are waiting on, and set some sort of mutex-protected boolean/flag to notify the thread that it should exit early (ie: mutexLock()l; bool bExitEarly = true; signal(condVar); mutexUnlock();).
  3. Assuming you spawned the threads as joinable (ie: non-detached), just make sure you have a copy of the pointer to each thread object, and call thread_join() on each of them after you've signaled them to stop. This will ensure that the threads are fully stopped before main() exits. If you don't do this, main() could exit before the threads are done, and just forcibly kill off the threads while they are in the middle of their shutdown logic, which is messy, and could cause your program to crash or worse.
Community
  • 1
  • 1
Cloud
  • 18,753
  • 15
  • 79
  • 153
  • I'm using pthreads. 1) Thanks gonna check that 2) So should I broadcast() to all threads currently waiting on a condition variable ? 3) Already did it. Thanks for pointing it out. – Levenlol May 10 '16 at 15:37
  • @Levenlol **(1)** Good. You should consider maybe writing some kind of wrapper for it if it's used in several threads. It will save you a lot of headaches down the road. **(2)** Yes. Signaling should be fine too, unless you have multiple threads waiting on the same condvar. Is that the case? If so, you'll want some sort of `bIsThreadAwake` flag for each thread to keep track of which ones received the broadcast in case one wasn't waiting when the broadcast took place (potential deadlock). **(3)** Good work. Seems you did your homework. If this helps, please consider marking it "Accepted". TY. – Cloud May 10 '16 at 15:44
  • 2) If the thread was awake and didn't received the broadcast ? I'm about to : before suspend (wait(cvar,mtx)) the thread check if it should quit in case pthread_exit. Can be a good solution ? – Levenlol May 10 '16 at 16:10
  • @Levenlol Yes, that could work (ie: lockMutex, checkFlag, unlockMutex, etc). You could have that check in more than one place in your code. Rather than having `pthread_exit()` calls littered all over your thread function code, just have one such instance at the end of the function, and write tidy code to get to that point. Same reason you don't want tons of `return` calls all over the place in a function unless you have a very specific requirement to do so. – Cloud May 10 '16 at 16:18
  • 1
    *Anyhow, only the root thread of your process (ie: the one that started with main()) will receive the signal.* plain wrong. `man pthread_sigmask`. – SergeyA May 10 '16 at 20:03