Reputation: 150
I have made a program which uses the fork()
function in order to make child processes. Its child processes do some work, but I want them to terminate when they receive a SIGTERM
signal from the parent process. Before exiting, I also want them to clean up arrays that I have allocated and send some stuff through FIFOs to the parent process. So I have 2 scenarios.
Global variables for my arrays as well as file descriptors for the FIFOs and then exit through the signal handler function, for example:
/*global variables*/
struct whatever ** test;
int test_size;
int fd_in, fd_out;
/*handler*/
void shutdown(int signo)
{
/*free memory for the arrays malloc'd through the program*/
/*send message with the help of fd_out*/
/*close fd_in and fd_out*/
_exit(0);
}
Declare a global int flag and when the child processes perceive that the flag has changed, they then clean up the arrays, send messages and exit.
/*global variables*/
int exit_flag=0;
/*handler*/
void shutdown(int signo)
{
exit_flag=1;
}
/*child process*/
int main()
{
/*declare fds and arrays*/
/*use sigaction and set up handler*/
while(!exit_flag)
{
/*do stuff*/
}
/*free memory*/
/*send message with the help of fd_out*/
/*close fds*/
}
My question is which scenario leads to good coding/programming? Are they both the same or there is a better and even more correct way to do this?
Upvotes: 0
Views: 1343
Reputation: 41
Your second implementation is considerably less error prone than your first. If you are freeing/closing resources, you must be certain that the active process is not using those resources. Since you are receiving an asynchronous signal, there is no good way to be certain that your process is in a suitable state to release those resources without having race conditions.
Additionally, you most likely will need to perform these cleanup routines on other conditions as well (error, completion, etc.) so these routines would likely be redundant if implemented in the handler.
On a separate note, it is good to get in the habit of declaring global flags as volatile
to ensure that your compiler won't optimize the flag to a constant and get you stuck in an infinite loop.
volatile int exit_flag=0;
Upvotes: 1