I have this code where I use sigaddset and sigaction. However if I comment segaddset the result is the same
struct sigaction act;
act.sa_handler = process_alarm;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
//sigaddset(&act.sa_mask, SIGINT);
sigaction(SIGALRM, &act, NULL);
for(;;)
{
alarm(3);
pause();
}
Why do I need to use it?
You are doing 2 things here:
Populating a sigset_t. A sigset_t is just a collection of values for signals, and are used in various system calls. You can:
Create an empty sigset_t (sigemptyset()
Add a signal to the set (sigaddset())
Remove a signal to the set (sigdelset())
etc...
Setting the signal mask for the signal handler. You do that by manipulating the sigset_t sa_mask member of the struct sigaction when you set up a signal handler in with a call to sigaction().
The signal mask of a signal handler means that while the signal handler is executing, the signals that are in the mask will be blocked - i.e. those signals will not be handled as long as they are blocked. When the signal handler are finished, the signals in will be unblocked.
A signal that is blocked isn't "lost", it will be handled when that particular signal is unblocked again.
The sigaddset(&act.sa_mask, SIGINT); means the the SIGINT signal cannot occur while the code for the SIGALRM handler is running.
On the other hand, if you comment out sigaddset(&act.sa_mask, SIGINT);, you're left with just an empty list of signals created with sigemptyset(&act.sa_mask);. So any signals that occur while the SIGALRM handler function is running might preempt that handler and execute the signal handler for that other signal.
For a SIGINT, you would normally not notice any difference with manual testing - it's unlikely you manage to hit CTRL-C exactly when your handler for SIGALRM is running, and your SIGALRM handler probably runs quickly enough that you would not notice if the SIGINT was slightly delayed.
Signals sets are manipulated via sigset_t type. Several operations are available for signals sets:
create an empty set S via sigemptyset, S=∅
add a signal s to a set S via sigaddset, S=S∪{s}
remove a signal s from a set via sigdelset, S=S\{s}
create the set of all possible signals via sigfillset.
test is a signal s is in a given set S via sigismember, s∈S?
Such a set is used at different places: setting a new process signal mask, blocking set during signal handling, requesting the set of pending signals, etc.
If you want to catch different signals, it may appears that some catching functions must not be interrupted with others, so you can add a set of signals to be blocked during the delivery of a given signal. You actually decided (when uncommented) to block SIGINT during SIGALRM delivery. So you can only observe this by sending a SIGINT during the execution of the handler; which is difficult to realize.
A example where it can be important ?
Suppose that the handler of SIGUSR1 modify a given data structure and that the handler for SIGUSR2 uses that same data structure. It is very important to make both handlers not concurrent, one can be run after the other but you probably don't want to be interrupted by one during the delivery of the other. Your code is self-concurrent, say that even in the case of only one thread, signals can lead you to concurrency.
sigaddset is used for adding the corresponding signal mask to that sigset_t variable.
In sigaction, it is not required. You can use that when you are using the sigprocmask which is for blocking the signal which we mentioning in that variable.
Related
I am working on a project involving signal-driven I/O which may end up using a signal handler created with sigaction(). My concern is that the handler might be called multiple times. In other words, it will be processing message A, when it gets interrupted by message B and start processing B, possibly causing a problem. I have seen some code on the web that uses sigprocmask to avoid this, but it appears wrong to me. For example:
void handle_signal(int sig_num)
{
sigset_t mask_set; /* used to set a signal masking set. */
sigset_t old_set; /* used to store the old mask set. */
/* re-set the signal handler again to catch_int, for next time */
signal(SIGINT, catch_int);
/* mask any further signals while we're inside the handler. */
sigfillset(&mask_set);
sigprocmask(SIG_SETMASK, &mask_set, &old_set);
.... (content handling code here) ....
/* restore the old signal mask */{{/COMMENT_FONT}*/
sigprocmask(SIG_SETMASK, &old_set, NULL);
}
This is obviously wrong because sigprocmask is not atomic with the signal. In other words, there is a window of time between when the signal handler is called and when sigprocmask is called, and the signal handler could be called a second or third time in that window, creating a race condition.
My options:
(1) Use a semaphore inside of the handler to queue any redundant calls of the handler.
(2) Write the handler to be re-entrant, so it is fine for it to be called multiple times concurrently.
(3) Some other solution?
If I go for option (2) above, can I consider a socket read queue to be thread safe? For example, let's say a socket handler gets called twice. Instance A starts reading from the socket, then it is interrupted, and Instance B starts finishes reading the packet. Will this cause A to just find the queue empty and finish up or will I be at risk for some kind of error?
If you're using sigaction to setup the signal handler then the signal that caused the handler to be triggered will by default already be blocked inside the handler.
In your code then the blocking of all signals and then the restore of the old mask is about blocking all other signals, the original signal (that triggered the handler) will be blocked until you return from the handler (or you specifically unblock it).
With sigaction you can avoid doing this block and restore in the handler by setting the sa_mask field of the struct sigaction, which is the set of signals blocked in the handler.
Further, your use of signal to "re-set" the handler is a little confusing, you call your function handle_signal then you re-set to catch_int (assuming this handler is actually handling SIGINT...
The older signal API did used to reset the signal handler back to the default each time the handler was triggered. However, by default sigaction does not do this, so you shouldn't need to "re-set" the signal handler if you're using the sigaction API. I personally would avoid mixing calls to signal and sigaction in the same program, I'd choose one and stick to it.
In conclusion, I think your concerns about sigprocmask not being atomic are unnecessary as the signal in question is already blocked, your mixed use of signal and sigaction worries me more.
I have a program that uses a signal (SIGUSR2) for setup a catch handler function to process high priority incoming messages.
The program receives incoming messages off an IPC message queue using msgrcv() in its main loop. When the sender of messages to the IPC message queue wants to notify the program that a high priority one is incoming, it sends SIGUSR2 to the process to have it stop processing any current message that may be being processed.
In the signal catch handler function I first upon entry do:
signal(SIGUSR2, SIG_IGN);
to ignore any new signals for preemption to occur.
then the code processes the preemption request where it stores the currently being processed message back into the queue, housekeeping, etc. and then just before returning from the signal handler function it does:
signal(SIGUSR2, sighandler_func);
Question: If another flash processing signal is received just a nanosecond after
the above signal call is issued, will the process re-dispatch to the
signal handler function again? ie: if the code in the main loop where
it does the sighold(SIGUSR2) and sigrelse(SIGUSR2) to stop / start the
receipt of the preemption signal take precedence or is it just the
above signal call that re-energizes the signal handler?
You should use sigaction for that:
struct sigaction act;
memset(&act, 0, sizeof(act);
act.sa_handler = sighandler_func;
sigaction(SIGUSR2, &act, NULL);
This way, the signal handler is automatically called with the signal blocked, which caused the event (in your case SIGUSR2). If now a SIGUSR2 arrives during the execution of the handler, it is blocked until the signal handler returns. Then, (when the signal is unblocked), the signal handler is called immediately again.
However, you will have to handle the case, that multiple SIGUSR2 arrive during one execution of the signal handler properly, since it will be called only once after return of the handler then.
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.
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.)
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.
In a single threaded program, does a race condition is possible in a signal handler?
void signal_handler(...)
{
static int i = 0;
i = i + 10 * 10;
}
Imagine that two very close signals are thrown, so close that they enter the function at the same time.
I can't find informations about how recent Linux OS handle this. I just know that both signals are correctly handled but I don't know how. Does race conditions are possible ?
Any helps appreciated, thanks!
There is no race condition in the sense that you mean (between two signals). Multiple signals of the same signal are not delivered simultaneously. Unless precautions are taken, multiple signals for different signal numbers may be delivered simultaneously, as described in torek's answer.
Whenever you involve variables of static duration (or global variables), your function may no longer reentrant. This is typically not important for the signal handler function itself. However, if it calls some other function that accesses global or static data, then that function will see an access pattern that is similar to two threads racing through a critical section. That is, your program is calling such a function to do its normal processing, but the signal arrives in the middle of that function, and then your signal handler calls into that same function. The global/static variables may be in an inconsistent state, and might cause your program to have non-deterministic behavior.
POSIX defines a set of APIs that are safe to be called from within a signal handler. Your code should take similar precautions when you plan to let your signal handler call functions that you implement.
Single threaded means only one app touching the static at a time yes? If there are 2 apps, there are 2 statics and no race condition.
If this is an interrupt handler and i += 100 is not atomic (which it may be depending on the platform/CPU), then it would race.
One additional, important note: if you're using "reliable signals" (POSIX sigaction with the corresponding sa_mask field), you get control over how signals behave in a single-thread-single-process situation.
Consider the case of single process P1, with a signal-handler like the one you show above. Suppose that you are catching signal SIGUSR1 and having that enter the function signal_handler. While you are inside signal_handler, some other process P2 sends another SIGUSR1 to P1 (e.g., via kill). This signal is "blocked" (temporarily) via sa_mask until signal_handler returns in P1. This is true even if you don't set any bits in sa_mask (as long as you don't set SA_NODEFER in sa_flags, see below).
But, suppose you've also decided to catch SIGUSR2 with function signal_handler. Suppose that P2 also sends a SIGUSR2. In this case, the SIGUSR2 is (or may be) caught, starting another instance of signal_handler running, this time on behalf of the SIGUSR2 signal.
You can prevent this by making sure that when SIGUSR1 is being handled, SIGUSR2 is temporarily blocked as well. In general you'd probably want to make SIGUSR1 blocked while SIGUSR2 is being handled. To do this, set both corresponding bits in sa_mask:
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_flags = SA_RESTART | SA_SIGINFO; /* (decide for yourself which flags) */
sigaddset(&sa.sa_mask, SIGUSR1);
sigaddset(&sa.sa_mask, SIGUSR2);
sa.sa_sigaction = signal_handler;
error = sigaction(SIGUSR1, &sa, NULL);
if (error) ... handle error ...
error = sigaction(SIGUSR2, &sa, NULL);
if (error) ... handle error ...
The two sigaddset calls make sure that both SIGUSR1 and SIGUSR2 are held-off (blocked, temporarily) for the duration of the function.
If you're only catching one signal, there is no need for this extra complexity, because as long as SA_NODEFER is not set, the OS automatically adds whatever signal triggered entry to your signal handler to the "currently blocked signals" set at entry.
(Note that the OS's automatic blocking and unblocking of signals at entry and exit to your signal handler is done with sigprocmask, using SIG_BLOCK and SIG_SETMASK—not SIG_UNBLOCK—with the mask for the SIG_SETMASK at exit set by saving the previous mask filled in via SIG_BLOCK. Well, it's normally done inside kernel code, rather than actually calling sigprocmask, but the effect is the same, just more efficient.)
The sa_mask field of struct sigaction specifies signals that are blocked during handler invocation. Those signals are added to the process block mask just before the handler is invoked and removed right after handler completion. What if sa_mask and the process signal mask overlap? Will those signals that are masked both by sa_mask and the process signal mask be removed from the process signal mask?
When a signal handler returns, the signal mask that was in effect before the signal was handled gets restored atomically as part of the return process. This will happen unless you jump out of the signal handler with longjmp or siglongjmp, in which case it's up to you whether you want to manually save and restore the signal mask.
As an interesting aside, if you use the SA_SIGINFO flag to setup a three-argument-form signal handler, the ucontext_t pointed to by the third argument contains a sigset_t uc_sigmask member reflecting the saved signal mask. Further, I'm not sure whether this usage is sanctioned by POSIX, but on all real-world systems I know of, you can actually modify uc_sigmask before returning from the signal handler to set a different signal mask (as opposed to restoring the original one) when the signal handler returns. This can be used, for example, if you want to re-raise the signal you just handled but leave it blocked when returning, so that it actually gets handled later on when the signal is again unblocked by the interrupted code or when sigwaitinfo or similar is called.
Will those signals that are masked both by sa_mask and the process signal mask be removed from the process signal mask?
No. The original signal mask is restored, ie. what was blocked before would be blocked after.