I am working on signals in C programming. I have parent process and 5 child processes, I am trying to send SIGUSR2 from child processes to parent process when they are done some calculations while parent waits for them with sigsuspend(). When all 5 child processes sends SIGUSR2, parent process continues its work. I increment a global variable in the signal handler function to do so. Sometimes it runs fine but sometimes parent process gets stuck waiting.
Can one of you guys help me with a better solution approach rather than counting the signals received (I must use signals for synchronization)?
To the best of my knowledge, you can't use signals for that. If two signals of the same kind are sent to a process before it gets scheduled to handle the first one, it will only see one signal. Think of it as a bit mask, there is one bit for each pending signal, and when the process gets scheduled it will receive them all. But if it is waiting for some other process, and a signal for which the bit in the mask is already set, then nothing more happens.
A better solution would probably be to open a pipe to each subprocess, and each of them writes a message when done. When the parent has read the message from all children, it can continue. There are other synchronisation methods, but this would probably be the simplest.
Related
I want to write a program that uses only SIGUSR1/SIGUSR2 signals for pausing and resuming a multiple number of child processes that work on a same problem simultaneously. If I use a signal handler to send an info that a child process has paused of course when its multiples are sent they will merge into one. Since I am using sigsuspend, is there a way to know when at least the last process finished so that i don't signal a parent before the last child finishes. Also, if that is not possible is it possible to somehow find out that child process is suspended by checking some of those 3 files made when a process is created. Thanks in advance!
I have process which forks a lot. Child processes do lot of stuff and another system calls.
When ANY child process gets error from system call, it prints error description to stderr and send SIGUSR1 to group leader (main parent process).
SIGUSR1 tells parent to kill all child processes, free resources and exit program execution (to avoid zombie processes).
I need to kill all children at once. Atomically. So when any error happens in ANY child process, all child processes stops with their work immediately.
Currently parent process kills all child processes with SIGUSR2 - It sends this signal to all process group members (killpg) - all of them have signal handler installed which kills them (exit) - group leader won't get killed though (it still needs to free resources).
The problem is that before all child processes get killed, they still can execute about 1-2 rows of code, which is not what I want. I need to stop them immediately.
How can I achieve this?
Signals are delivered in a async fashion, since both parent and child processes are running, you cannot expect the child process will handle the signal immediately when parent send the signal.
The problem is that before all child processes get killed, they still can execute about 1-2 rows of code, which is not what I want. I need to stop them immediately.
Your problem is more of a coordination and synchronization between processes, rather than signal handles. There are two ways I can think of:
Use synchronized signals. That is when each child send SIGUSR1 to the parent, they stop working, and wait on SIGUSR2 signal by the waiting functions, like sigtimedwait, or sigwait, in this way, they will not run any additional code before exiting.
Use pipe or socketpair to create communication channels between parent and children, that is, parent send kill instruction to children, and each child will free necessary resources and kill themselves. This requires children to listen on the channel while doing work.
Do you mean that all child processes must stop working as soon as the faulty child send SIGUSR1 ?
If this is what you want, I don't think you can achieve this the way you are doing: when the faulty child sends SIGUSR1 to the leader, the other childs will continue execution until the SIGUSR1 is processed by the leader.
Do you really need the faulty process to send SIGUSR1 first to the leader ? Would not this be possible that the faulty process directly sends SIGUSR2 to the group, which signal can just be ignored by the leader (or, at least, not processed as a termination signal) ?
http://codepad.org/rHIKj7Cd (not the whole code)
What I'm trying to accomplish, is the parent to write something in the shared memory, then the child to react accordingly, and write something back, every five seconds. I thought about using SIGUSR1-2, and maybe switching on signum in the handler, but I don't know how to code that in, because setitimer throws SIGALRM. I obviously don't want to fork in the handler, cause i only need one child and one parent, so how do i define the different behaviour? I hope my goals are clear:
Every 5 seconds:
SIGALRM is thrown by the timer
Parent writes its calculations into shared memory (semaphores are being used)
Child reads from shared memory, writes back it's calculations
I also know signal() is not adviced to use, this is not the point.
The timer signal handler should do as little as possible, possible only a "post" operation on a semaphore the parent process waits for. The parent process then does it work, and in turn uses "post" on a semaphore the child waits on. The child does its work and signals back to the parent via another "post" and then goes back to waiting for the semaphore, and the parent can do something with the result from the child. Lastly the parent process goes back to wait for the semaphore from the timer signal handler.
Of course, the signaling between the processes, and from the timer signal handler to the parent process, doesn't actually have to be semaphores. There are other ways to communicate and sending "signals" between processes in a POSIX system, including reading/writing from/to pipes, setting special bits or bytes in shared memory, or message queues.
I am writing a C program in which the parent forks n child processes. A child process once created invokes a SIGSTOP to allow other child processes to be created. The parent after creating all the n child processes sends a SIGCONT signal to all the child.
All the child processes execute an infinite loop and share a common resource using semaphores. Now I want that whenever the user presses ctrl-c, the parent and all the child processes terminate together. However before terminating the child processes should update in a file how many times each has used the resource.
eg:
Process 1 - 5 times
Process 2 - 3 times
and so on.
Need help in this implementation please...
The formal signal handler function should do as little as feasible. The C standard says it can write to a volatile sig_atomic_t variable, or call abort() or _Exit() (or, with restrictions, signal()). POSIX allows more to happen, and you're probably working on Linux (though you didn't say so). So, your signal handler will change the value of a sig_atomic_t variable from 0 to 1 to indicate that the signal occurred.
So, your child processes will be looping. As part of the loop condition, you should check a sig_atomic_t variable to see whether the child should terminate. When it detects that a signal occurred, it will stop looping, open the log file for append, write its information to that file, and exit. You could check the sig_atomic_t variable at other points in the processing than just the main loop condition; that's your decision.
Note that you should use sigaction() rather than signal() to control the signal handling, and you should block interrupts while processing a signal.
So, to summarize:
Your signal handler does as little as possible.
Your code detects in the main loop when the signal handler has been called and arranges to exit.
Your code can also detect when the signal handler has been called at other convenient points.
You can call a function to do the logging and exit.
In order to write the file, you need to add the code to write to said file in your signal handler for SIGINT. If you want each process to write to that file, you're going to need to make sure that the SIGINT gets sent to the entire process group.
You can probably get by without sending the SIGQUIT to each, as you could have each process simply exit itself after processing SIGINT. If you want to optimize a little, you could keep a shared data structure of which processes have already received the SIGINT so that you don't send each process several SIGINTs.
I want to be able to handle many signals of the same type (SIGCHLD), but, I want to make sure that if a signal is arriving while I'm still handling the previous one, I will finish handling the first to arrive, and only after I finish handling it, I'll handle the next ones.
There may be more than one signals waiting to be handled.
Also, does a process sends SIGCHLD if it's terminated or killed (using SIGTERM/SIGKILL) by the parent process?
As long as you use sigaction and not the problematic signal function to setup your signal handler, you can be sure (unless you specify otherwise) that your signal handler will not be interrupted by another occurrence of the signal it's handling. However it's possible if many child processes all die at once that you might not receive a signal for each. On each SIGCHLD, the normal procedure is to attempt to wait for children until your wait-family function says there are no children left to wait for. At this point, you can be sure that any further child termination will give you a new SIGCHLD.
Also, since you're very restricted as to what functions you can use from a signal handler, you'd probably be better off just setting some sort of flag or otherwise notifying your main program loop that it should check for terminated children via one of the wait interfaces.
And finally, yes, a SIGCHLD is delivered regardless of the reason the child terminated - including if it was killed by the parent.