C Signal usage and process using IPC message queues - c

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.

Related

How to avoid race condition in signal handler

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.

Multiple signals arriving at handler

I have a main process that has forked some kid processes.
Each kid does something and blocks itself. By blocking itself every child sends a SICHLD signal to the parent process.
I also have declared a sigaction action, in the main process code, in order to catch the SIGCLHD that the kids will send.
static struct sigaction action;
action.sa_handler = handler
sigfillset(&(action.sa_mask));
sigaction(SIGCHLD, &action, NULL);
The SIGCHLD handler when called, checks which kid sent the SIGCHLD signal and does something for that kid.
The question is, what happens if multiple kids send signals at the same time? Let's say that kid(1) sent SIGCHLD. The handler catches it and before he completes the handle, kid(2) and kid(3) both send signals. Will the handler run for each of these signals after he is done with kid(1) or will these signals get ignored?
SIGCHLD is somewhat special in that you get exactly one signal per exiting child; these signals are tied to the corresponding zombies/wait-status left behind by the child processes they correspond to. But in general most signals are just flags, not queues. If possible it's best not to use SIGCHLD and instead just use waitpid and track child exit in some other way (e.g. by observing EOF status on a pipe from the child in your poll loop or such).

What is sigaddset used for?

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.

Create signal handler for a single thread

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.

Signal queuing in C

I have a simple program under Linux which sends SIGUSR1 signal to its child process in a cycle. But when I send e.g. 10 signals, sometimes happens, that the child received only 3 of them. Last sent signal is always SIGUSR2 and that is received every time.
Are the signals queuing, or when process didn't process the previous, it is simply overwritten? Is there a way I can send signals in a queue?
What happens is the following:
First signal received, namely SIGUSR1, handler is called and is running
Second signal received, since handler from nr1 is still running, the signal nr2 gets pending and blocked.
Third signal received, since handler from nr1 is still running, the signal 3 gets discarded.
Fourth, fifth...etc signal of the same type as the signal nr1 are discarded.
Once signal handler is done with signal nr1, it will process signal nr2, and then signal handler will process the SIGUSR2.
Basically, pending signals of the same type are not queued, but discarded. And no, there is no easy way to "burst" send signals that way. One always assumes that there can be several signals that are discarded, and tries to let the handler do the work of cleaning and finding out what to do (such as reaping children, if all children die at the same time).
If multiple signals of the same type are sent and not handled, they aren't queued. Say the program masks SIGUSR1, calls kill(getpid(), SIGUSR1) 10 times and unmasks SIGUSR1. It will receive SIGUSR1 just once.
Your problem is probably that SIGUSR2 is a signal that is delivered right away, while other signals are blocked or queued (in status pending).
Here's how you can check for pending signals: http://www.gnu.org/s/libc/manual/html_node/Checking-for-Pending-Signals.html
So doing simultaneous I/O of many files with SIGIO seems possible only if one uses flag SA_NODEFER for struct sigaction sa_flags field and never blocks signals.
So then, one could get interrupt from inside a signal handler and create new thread for each individual signal being handled. That gets complicated :) So no wonder why no one seems to use SIGIO.

Resources