Signal Handler why it is blocked while handling the same signal - c

For theory purpose: I associate handler for SIGINT, by using signal (). When the this signal is handled, ie, signal handler is executed, by default the same signal is blocked. What is the reason behind blocking ?. Does it lead to deadlock kind of situation ? Kindly clarify.

Because signal handlers are not expected to be re-entrant.
A signal handler typically runs quickly and should call only async safe functions, i.e. a very restricted set of functions, see signal(7).
You usually don't want it to be callable inside itself.
Unless you don't return normally from the signal (or do a siglongjmp inside it), the previous signal masks are restored after the signal handler completed.
However, you can install a signal handler (thru sigaction) which does not block itself.
For similar reasons, on usual processors, the intterupt handlers are also running quickly and are disabling interrupts.

Related

Does multi-thread program handle multiple signals in parallel?

Platform is Linux/POSIX.
The signal is sent to a whole process, not a specific thread.
No signal is set to blocked, all default.
The process is multi-thread process.
From what I've googled, a signal may be handled by a random thread.
And when that signal's handler is executing, it's temporarily blocked until handler returns.
QUESTION: Multiple signals of different types reached simultaneously. Do their handler execute simultaneously on multiple thread or all of them go to one randomly picked thread (SUB-QUESTION: in this case a handler could interrupt another handler's execution started previously, so there could be a interrupt stack?) ? Or mixed? For instance there are 3 type of signals received but only 2 thread free (this is actually the first case).
EXAMPLE: SIGHUP, SIGINT, SIGTERM reached almost simultaneously. The program has two available thread to dispatch signal handler execution.
SIDE-QUESTION: If signal handlers run in parallel, I'll have to use mutex to synchronize them properly. Otherwise 'volatile sig_atomic_t' would be enough, right?
Expected: all signals go to one thread (randomly picked) despite of their different signal types, I haven't seen an example of using mutexes and atoms to synchronize signal handlers.
Your understanding is correct - unless a signal was directed
to a specific thread, there's no guarantee which thread will handle a signal.
See POSIX's Signal Generation and Delivery and pthreads(7):
POSIX.1 distinguishes the notions of signals that are directed
to the process as a whole and signals that are directed to
individual threads. According to POSIX.1, a process-directed
signal (sent using kill(2), for example) should be handled by
a single, arbitrarily selected thread within the process.
So it may be delivered & handled by the same thread that's currently handling another signal (in that case, the previous handler may be interrupted by the new signal). Or may be delivered to another signal.
You can block other signals while one is being handled using sa_mask field
of sigaction to avoid a signal handler being interrupted.
SIDE-QUESTION: If signal handlers run in parallel, I'll have to use mutex to synchronize them properly. Otherwise 'volatile sig_atomic_t' would be enough, right?
You almost certainly don't want to use mutex in a signal handler. There are only few functions that can be safely called from a signal handler (you can only call the functions that are async-signal-safe).
See signal-safty for more information.
If you can use volatile sig_atomic_t for whatever the purpose (do you need to co-ordinate execution of different signal handlers?), it should be preferred.
Expected: all signals go to one thread (randomly picked) despite of their different signal types, I haven't seen an example of using mutexes and atoms to synchronize signal handlers.
This is commonly done by blocking signals that you're interested in from main and fetching/handling them in a specific thread. See pthread_sigmask which also has an example on how to implement this.

Are all threads halted when one of them receives a signal and none of them block it?

I'm running a multithreaded application written in C on Linux.
To stop execution I send SIGINT and from the signal handler call a number of cleanup routines and, finally, call exit(0).
Are the other threads still running or may run (context switch) while the handler executes the cleanup routines?
Handling a signal does not cause the suspension of other threads during execution of the signal handler. Moreover, it's generally not safe to call most functions you would need for cleanup (including even exit!) from a signal handler unless you can ensure that it does not interrupt an async-signal-unsafe function.
What you should do is simply store the fact that SIGINT was received in some async-signal-safe manner and have the program act on that condition as part of its normal flow of execution, outside the signal handler. Then you can properly synchronize with other threads (using mutexes, condition variables, etc.) to achieve a proper, safe shutdown. The ideal method is not to even install a signal handler, but instead block all signals and have a dedicated signal-handling thread calling sigwaitinfo in a loop to accept signals.
Yes, a signal is delivered to one thread, chosen in an unspecified way. Only threads that aren't blocking the signal are considered, though; if all threads block the signal, it remains queued up until one thread unblocks it.
(So if you make all threads block the signal, you can use the signal as a deterministic, inter-process synchronization mechanism, e.g. using sigwait.)

Masking signal when global variables are being updated

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.

Returning from a signal handler and leaving signal masked

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)?

Is there a way to make process-internal-only conditionally-interrupting signals?

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...

Resources