4

I'm wondering if sigaction will create a signal handler for the calling thread or the whole process. If it unblocks a signal and creates a signal handler for the entire process, then how can I make sure only a single thread will use the signal handler and have other threads block the signal.

In my case, I want a single thread to call a signal handler when an alarm signal goes off and the other threads to simply block it.


void alarmSigHandler(int signo){

}

void* alarm_thread_start_routine(void *arg){

    // Perform some tasks

}


int main(){

    // Main thread start

    /* Unblock alarm signal */
    /* Assign signal handler for alarm signal */

    /* Launch alarm signal handler thread */

    /* Block alarm signal with pthread_sigmask */

    /* Do something */

    return 0;
}

http://vip.cs.utsa.edu/classes/cs3733f2013/notes/SignalsAndThreads.html

If a signal is sent to a threaded program, any of the threads can handle the signal.

Each thread inherits the process signal mask, but each thread has its own signal mask that can be modified with pthread_sigmask.

sigprocmask should not be used in a threaded environment, but it can be used before the threads are created.

The simplest way to handle signals in a multithreaded environment is to have a thread dedicated to signal handling.

Issues involving signal safety can be handled by using sigwait:

The main process blocks all signals before creating any threads.
No signal handlers are set up.
A thread is created to handle the signals.
That thread sets up a sigset_t containing the signals of interest.
It loops, calling sigwait and handles the pending signals.
sj755
  • 3,944
  • 14
  • 59
  • 79
  • To avoid the possibilty of races during handler setup the main thread should 1st ignore/block all signal and afterwards spawn off the thread(s) to receive any signal(s) and then the thread(s) which are to receive (a) specific signal(s) should set up the handler(s) needed its/themself(s). – alk Nov 19 '13 at 07:34

2 Answers2

3

You say:

In my case, I want a single thread to call a signal handler when an alarm signal goes off and the other threads to simply block it.

Try this:

void *alrm_thread(void *arg) {
  // install SIGALRM handler
  // unblock SIGALRM
  ... do stuff ...
}

int main(int argc, char **argv) {
  // block SIGALRM
  // spawn alarm_thread
  ... do stuff or spawn other threads ..
}

SIGALRM will only be delivered to the "alrm_thread" above.

UPDATE

(Adapting Alex Che's apt comments)

This works because each thread has its own signal mask inherited from the thread which creates it.

Masking (blocking) SIGALRM in main() right away ensures all subsequent threads begin life with SIGALRM blocked. Our special thread installs the handler and unblocks SIGALRM. Since this special thread is the only thread able to receive an ALRM, it will be the thread that runs the handler.

(Now, there are some signal nuances just around the corner. Handlers or signal dispositions are process-global attributes shared by all threads. Signals can be process-directed or thread-directed. However, for your case, which is a very common case, the above is suitable.)

Community
  • 1
  • 1
pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • This is actually an answer to the question (the practical part after "I want"). – Alex Che Nov 16 '16 at 13:33
  • It works, because while the signal disposition (signal handler) is the same for the whole process, the blocked signal mask may be different for each thread (and inherited from the parent thread). Therefore if we have the signal unblocked in only one thread, then the installed process signal handler will be called only in this very thread. – Alex Che Nov 16 '16 at 13:39
2

From the man page for signals:

The signal disposition is a per-process attribute: in a multithreaded application, the disposition of a particular signal is the same for all threads.

So yes, when you set a signal handler it will handle signals sent to the process; signals aren't sent to each thread individually, it is sent to any one of the threads that aren't blocking the specific message being sent.

chbaker0
  • 1,758
  • 2
  • 13
  • 27
  • 2
    But each thread can have a unique signal process mask can't it? I saw this response in that thread: `child thread inherits its parent thread's signal disposition; a thread can then alter its own disposition without affecting other threads (though any children it creates after changing the disposition inherit its then-current disposition)`. This tells me there may be a way for the original parent thread to block the signal and one child thread unblock it and assign it a signal handler. – sj755 Nov 19 '13 at 02:05
  • Yeah, I see that now. However, I think that only applies to signals that are related to faults (i.e. divide by zero, segfault, etc) and a signal like you are describing would be a process wide signal that would be handled by the disposition for that signal on the process level. – chbaker0 Nov 19 '13 at 02:14
  • 1
    I have another idea. What if the main thread were to assign the signal handler, launch a child thread, and the main thread then blocks the alarm signal. I added some example code. Are you saying this would never work? – sj755 Nov 19 '13 at 02:28
  • Good question. I'm not sure, but I found this in that man page: `If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.` I think that means in your case, the message would be queued until the child thread executes, then the function will be called while the child thread is running. – chbaker0 Nov 19 '13 at 02:38
  • 1
    I found [this post](http://stackoverflow.com/questions/11679568/signal-handling-with-multiple-threads-in-linux) that may be helpful. The second answer on there actually has a snippet of code from the Linux kernel that is well commented and might better describe how the messaging will work for you. – chbaker0 Nov 19 '13 at 02:44
  • I was just looking at that post. I've also looked up the notes of a professor whose book I have in my possession. I updated my post to include his suggested approach. – sj755 Nov 19 '13 at 02:57
  • That looks like a good solution. May I ask though, why you want to avoid any other threads from receiving a signal? – chbaker0 Nov 19 '13 at 03:03
  • I'm developing a multithreaded application that simulates controller that changes states after a certain amount of time. One thread manages data and another manages the state information. I was initially gonna have the data controller handle state transitions with a signal handler, but now it seems a separate state controller thread would be a better solution. I would only want this thread to ever see the alarms and do all the logic in reaction to them. – sj755 Nov 19 '13 at 05:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/41473/discussion-between-mebob-and-sj755) – chbaker0 Nov 19 '13 at 13:48