When is a pending signal no longer considered pending? - c

I'm reading about signals and I read that a signal that has been sent but not received is considered pending. Additionally, control jumps to a handler whenever a OS does a context switch to some process and discovers a pending and unblocked signal.
When is the bit for a signal in the pending bitmask cleared? Is it only when the handler finishes processing the signal? Or is it cleared the moment control jumps to the beginning of the handler?
I'm curious because I'm not sure what happens if for example, a SIGINT signal arrived while a SIGINT handler was already processing the signal and chose not to block further SIGINT signals. (I read that by default, signal handlers for signal K will block signal K by default but I'm wondering what happens if it is unblocked)

Related

Is it possible to clear all signals received when switching between `ucontext_t`?

I currently have a ucontext that will block SIGINT, let's call this context A, while I want the rest of the contexts to handle the signal when they receive SIGINT. The issue is that if A receives SIGINT, it does block it but, the second I setcontext, the signal handler is immediately called. Is there a way to reset the signals when I change between processes?

Signal can't wake up sleeping process

I'm working on a project which requires to take care of process scheduling. I tried to stop certain process by sending SIGINT signal(ctrl+c), but i found out sleeping process doesn't wake up.
I solved this weird issue but couldn't find out why SIGINT signal couldn't wake up sleeping process.
Here's my original code (where process is stuck) :
set_current_state(TASK_INTERRUPTIBLE);
while (!item->assigned) {
schedule_timeout(2*HZ);
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
So inside of the while loop, when !item->assigned is still 1, SIGINT signal doesn't do anything even though process' state is set to TASK_INTERRUPTIBLE.
As far as I know, process takes care of signal in these ways:
execute the signal default action
block the signal setting a signal mask (this is done using the system call sigmask)
assign a custom handler to the signal, executing a custom action (using the system call signal)
So in this case I assumed It would execute the default action..
I added signal_pending(current) to check if there is any pending signal, and if it is, then break out of the loop so that the process can handle the pending signal.
set_current_state(TASK_INTERRUPTIBLE);
while (!item->assigned) {
schedule_timeout(2*HZ);
if (signal_pending(current))
{
break;
}
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
But still no idea why It didn't catch the SIGINT signal.

Does signal "auto-block" (when execution enters handler function) prevents another such signal from being delivered to another thread?

Signal mask is thread-specific, which means blocking a signal doesn't prevent it from being delivered to another thread where this signal isn't blocked. When execution enters into a handler function (assuming no SA_NODEFER) "current" signal becomes blocked.
Does it mean it will be blocked for all threads in current process or it is possible for next such signal to be delivered to another thread (while it is still being handled in first thread)?
Reading man sigaction:
sa_mask specifies a mask of signals which should be blocked (i.e., added to the signal mask of the thread in which the signal handler is invoked) during execution of the signal handler. In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.
This sounds like the masking of the currently handled signal only affects the handling thread, so other threads may handle further signals.
I think it is typical for a multithreaded system to block all signals for all threads except one (or several) dedicated signal handling threads (e.g. one that is polling on a signalfd). That way you never have to worry about signals landing on some unpredictable thread.

How to wait inside SIGABRT signal handler

I have a signal handler for SIGABRT , when the signal is received, i need some more time for other threads to exit gracefully. Then I will do _exit() inside signal handler to exit the entire process.
But I am not sure how to wait inside a signal handler. I think there are some limitations for using sleep inside signal handler. I dont want to use busy wait.
Somebody suggest any ideas please ?
There are no limitations of what kind of code you can execute inside a signal handler. You just have to keep in mind that another signal may arrive while executing your signal handler leaving you in the middle of half finished functions, locked mutexes or other things that should better remain uninterrupted.
Normally you would have the signal handler set a flag signalling to all threads to nicely exit, return from the signal handler and then have your code gracefully exit.

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