I am aware that i can mask a signal from being raised when handler is executing (by using sa_mask). However, i would like to know how to mask a signal when i am updating some global variables.
Also, i would like to know how to mask a signal when a particular user defined function is executing.
Is it possible to do these 2 things?
Any help will be appreciated
Thanks
You can call "signal()" any time you want; either to a) set the signal handler to some custom code, or b) clear it by setting the handler argument to NULL.
sigaction(), of course, gives you even finer-grained control. You can call sigaction whenever you wish (for example, before updating your global variables), too.
This link might help:
http://www.linuxjournal.com/article/6483
It's possible to block signals with sigblock(). Signals blocked will be queued and released when the signal is unblocked.
HOWEVER - this is super expensive. You have to do a syscall to block and a syscall to unblock. This can be quite slow if you do it often. So there are some alternative approaches:
If you're on linux, use signalfd. You can block all signals once and redirect them to a file descriptor, then handle them whenever it's safe to do so.
Otherwise (or if async signal handling is important), you can defer signals in userspace. Before entering your critical section, set a volatile flag. In your signal handler, check for this flag; if you see it, write() to a pipe the signal number and immediately return. In your signal handler, check back for a signal on this pipe, and re-raise the signal at that point.
Related
I have SIGINT handler. It sets variable for whole program: errflag. When I do select() and it's interrupted via SIGINT, I check errflag to see if it's SIGINT (have own constant assigned to errflag). However, the handler can be late and errflag isn't yet set. How to defer processing before handler's resolution on errflag? Or how to implement this correctly?
Also, in one code path select() returns -1 on Ctrl-C, errno is EINTR. Here handler is never late. In other path select() returns -1, errno is also EINTR, but handler outputs log message little later and is late, my errflag checks are already performed.
However, the handler can be late and errflag isn't yet set.
Er, what? No, it can't be "late". Something else is wrong here.
Signal handlers interrupt normal program flow -- when SIGINT is received, your handler runs, and control flow is only released to the rest of your program when the signal handler exits.
What you do need to make sure of is that errflag is declared as volatile, so that the compiler will not make undue assumptions about when its value can change.
What you also need to keep in mind is that printf() is not safe to use in signal handlers, as it may use global buffers which can be left in an inconsistent state during signal handling. Generally speaking, very few things are safe to do during a signal handler besides setting volatile global variables or exiting. Trying to use printf() in a signal handler may result in inconsistent, confusing results; the output should not be used as a reliable indicator of what actually happened in your program!
I've got a situation where a signal handler needs to, under certain conditions, return without unmasking itself, i.e. after returning the signal should remain blocked in the thread's signal mask. Jumping out of the signal handler with longjmp will not work because I need to return to the exact point that was interrupted like a normal signal handler return. Is there any conformant way to do this, short of using the ucontext_t which was removed from the standards? I cannot change signal handlers or dispositions; all effects must be local to the thread.
The purpose of this code has to do with some atomic operations and potential for a race condition or deadlock. Basically the potentially interrupted code looks like:
atomic_write(&thread_local_flag, 1);
atomic_dec(&global_counter);
If the flag has been set and the counter decremented, all is well and the signal handler has nothing to do, but the signal could possibly arrive between the two instructions. In this case, the signal handler wants to immediately return and let the decrement proceed, but the process is being bombarded with signals (intended to be received by all threads for an arcane synchronization purpose) and there's a possibility it could loop forever (or at least for unbounded time) processing signals while other threads never receive their signals.
If I could leave the signal blocked when the signal handler returns, there would be no problem.
Hmm, the best I've found so far.. This seems to work and does not depend on any ucontext functions, just the structure which was not removed. In the signal handler:
if (thread_local_flag) {
sigaddset(&((ucontext_t *)ctx)->uc_sigmask, sig);
return;
}
Here sig and ctx are the first and third argument to the SA_SIGINFO-type signal handler, respectively.
Any thoughts on whether this is correct usage or a horrible hack (or both)?
I'm looking for a way to, from within a signal handler, conditionally interrupt a syscall that way taking place at the time the signal was handled. To make this concrete, suppose a call to read is in process, and SIGRT0 is received. This signal handler uses SA_RESTART because it does not want to unconditionally interrupt syscalls, but depending on a condition, I want to cause read to return EINTR immediately once the signal handler returns.
One way I could do this is by setting up another signal handler for SIGRT1, putting SIGRT1 in the signal mask for SIGRT0's handler, and omitting SA_RESTART from the SIGRT1 handler. Then the handler for SIGRT0 can raise SIGRT1, and when the first, non-interrupting signal handler returns, the second one will fire and read gets interrupted.
The problem with this solution is that other processes could send SIGRT1, causing unwanted EINTR occurrences.
Is there any way to achieve the result I'm looking for?
If you want to set a particular process to send that signal then you can any IPC techniques (e.g. pipe) to share its pid id and flags to make sure that signal was sent by that process. If signal wasn't sent by the process then just ignore it.
What I wanted was impossible for multiple reasons. Perhaps most importantly, the secondary signal that was intended to do the interrupting would potentially (and in reality on most systems) fire as soon as the first signal handler returned but before the interrupted syscall got restarted. Then the syscall would restart and continue to block.
Perhaps more importantly, any attempt to interrupt blocking syscalls with EINTR intentionally is subject to race conditions where the signal arrives just before the blocking syscall, but after whatever check would have prevented making the syscall due to having received the signal. The only time this might be acceptable is when you're prepared to fire off multiple signals with increasing delays between them until the "interupt request" is honored, but that's getting into the realm of flaky hacks...
I need to know how to avoid a race condition when handling signals in C. Each time my program receives a signal, I want it to alter a (global) linked list. It is vitally important that I not miss a signal, and equally important that the global linked list I'm modifying not be changed while the handler is executing.
The problem is, if I receive a signal, and start the handler, but am then interrupted by another signal. This (as I understand it) triggers a new execution of the signal handler, which will operate on the same global dataset - not permissible!
I can't use a lock, because if the first handler call is interrupted, it will naturally never free the lock for the interrupting handler to pick up. So, how do I do it? Any idea?
If you have the luck to be working in a multi-threaded environment, one of the best ways is to have the global linked list controlled exclusively by a separate thread. Interrupts would enqueue requests to this thread (something that would be executed very quickly, say, by simply passing a pointer), and then the thread would procedurally go through each request and modify the linked list. This allows lockless execution.
Of course, you have to rely on your OS's message passing junk, so that may not be an option.
You can mask signals while executing signal handler - check sa_mask field of struct sigaction you pass to sigaction() syscall.
From http://users.evtek.fi/~tk/rtp/signals-programming.html:
The way to guarantee no races at all, is to let the system set the signal masking for us before it calls the signal handler. This can be done if we use the sigaction() system call to define both the signal handler function AND the signal mask to be used when the handler is executed. You would probably be able to read the manual page for sigaction() on your own, now that you're familiar with the various concepts of signal handling. On old systems, however, you won't find this system call, but you still might find the sigvec() call, that enables a similar functionality.
I think you should seriate the signal.just like the work queue
E.g. all the signal should put into a work queue(FIFO), and then the executing thread poll the queue all the time. if the queue is not empty,this thread will pick the top signal and start it`s handler. keep doing like that, until the queue is empty.
Any ideas on this? Is there some kind of a signal queue, or does it get dropped?
While we are at this question, is it true that signal handlers should do as minimal work as possible?
I read somewhere that a signal handler should use a pipe and just write one byte to it, indicating what the program should do. Then somewhere else the program periodically checks the pipe, and dispatches based on byte in it. (I might have misunderstood it)
Thanks, Boda Cydo.
To answer the second part of your question, "is it true that signal handlers should do as minimal work as possible?" the answer is yes, because there is a very minimal set of functions that are "async signal safe" and therefore able to be called from signal handlers. Async signal safety is kind of an enhanced form of re-entrancy. If foo() is async signal safe, that means that it's safe to call foo() within a signal handler, even if foo() was already executing when the signal was raised.
You can get the full list of async signal safe functions by looking that the section 7 man page for signal (man 7 signal). Calling any function other than one of these from within a signal handler, directly or indirectly, invokes undefined behavior.
The "write a byte to a pipe" approach is a great way to deal with signals without being restricted to async signal safe functions, especially if your program is already oriented around a select loop.
To answer the first part of your question, the default is as follows: If it's the same signal as the one currently being handled, the new signal is blocked (held in a queue) and delivered when the handler returns. If some other signal arrives, the handler for the new signal is called. c.f. the glibc manual.