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.
Related
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.
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!
Currently, I'm learning about processes on the UNIX system.
My issue is, I need to do something every time a background process terminates. That means that I can't use the typical functionality of waitpid because then the process won't be running in the background and it'll hang the program.
I'm also aware of the SIGCHLD signal which is sent whenever a child of the parent process is terminated however I'm not aware of how to get the process id of the said process which I will need.
What is the proper way to go about this in C? I've tried things such as WNOHANG option on waitpid however that of course only gets called once so I don't see how I could make that apply to my current situation.
waitpid because then the process won't be running in the background and it'll hang the program.
If the process won't be running in the backrgound, waitpid with the pid argument will exit immediately (assuming there are no pid clashes). And still, that's not true - just use WNOHANG...
however I'm not aware of how to get the process id of the said process which I will need. What is the proper way to go about this in C?
Use sigaction to register the signal handler and use the field si_pid from the second signal handler argument of type siginfo_t. From man sigaction:
SIGCHLD fills in si_pid, si_uid, si_status, si_utime, and si_stime,
providing information about the child. The si_pid field is the
process ID of the child
A working example that uses it is in the man 3p wait page under section Waiting for a Child Process in a Signal Handler for SIGCHLD.
What is the proper way to go about this in C?
The C standard is not aware of child processes and SIGCHLD signals. These are part of your operating system. In this case the behavior is standardized by POSIX.
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 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.