I have a child process which might receive sigterm signal from its parent or from somewhere else. I have to take appropriate action if the signal is from parent.
How can i find if the received signal is from parent in c(linux)?
You set up your signal handler with sigaction using the SA_SIGINFO flag. Your handler will accept a parameter of siginfo_t. Within the siginfo_t struct is the field si_pid. This is the process id of the sending process. Match that against the child's ppid().
Related
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).
I'm trying to understand the signal handling and process. I have a parent process that created several child processes. Now in the parent process I have a list of all child processes. when a child is terminated I want to delete it from the list. I know that when a child is terminated he's sending SIGCHLD to the parent. OK, now it's the tricky part, how can I find out if that child terminated or just suspended or something else?
As you said
when a child is terminated he's sending SIGCHLD to the parent
Make the parent call wait().
Either
by a blocking call to wait() or
on a continous base or
by seting up a signal handler serving SIGCHLD which in turn calls wait().
If having called waitpid() with a pid of -1 using the option WUNTRACED and then applying the macro WIFSTOPPED to the value returend by waitpid() it tells you whether the process was stopped or ended.
For Linux since kernel version 2.6.10 the same as for WIFSTOPPED applies to WCONTINUED.
There is a system call in signal.h - sigaction() , similar to siganl( ) but more useful.Visit http://man7.org/linux/man-pages/man2/sigaction.2.html
The signal handler function prototype for sigaction() looks like this:
void sa_handler(int signo, siginfo_t *si, void *ucontext);
It has an argument of type siginfo_t which contains all the information about the signal including the pid of the process which sent it.
Though using conventional signal handling mechanism, it can be done using waitid() as mentioned in previous answer(s) but waitid() needs pid as one of its argument.
Using the options argument of the wait() family of functions (waitpid(),waitid()).
http://linux.die.net/man/2/waitid
I am writing a simple program in which parent and child process are alternatively printing into a file. I have managed to do this using user defined signals. Now I want to handle the SIGINT signal. Once ctrl-c is received the parent must send termination signal to child,the child should then should terminate and finally the parent should terminate.
My question is, in order to make this work properly I must catch the SIGINT signal ONLY from parent and IGNORE it from child. Is it right? If yes any hints on doing this?
Call:
signal(SIGINT, SIG_IGN);
from the child process which will make the child process ignore the SIGINT signal. From man signal:
If the disposition is set to SIG_IGN, then the signal is ignored.
Suppose there are two processes, a parent and a child, which use the signal for synchronization. In the parent process, the function used to sync with child acts as below.
WAIT_CHILD(){
while(sigflag == 0){ //sigflag will be set to 1 in a signal handler in the child process
sigsuspend(&zeromask); //No signal is in the mask set
}
//do sth....
}
My question is can we use pause() to replace the sigsuspend(&zeromask)?
No. The posted code is only race-condition-free if the prevailing signal mask is blocking the signal that is sent by the child, and if that is the case then, since pause() will not change the signal mask, it would block forever.
The reason that the signal must be initially blocked is that otherwise, a signal could arrive in between the test sigflag == 0 and the sigsuspend(), which means the process would have missed the signal and get stuck.
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.