I would like to make the last child of a N number of child (generated by a fork) to kill his father.
I tried :
in the fork function
signal(SIGINT, processKilled);
int car_finished = 0;
for (int car = 0; car < CAR; car++) {
int pid = fork();
...
}
in the son
car_finished++;
if (car_finished == CAR-1){
kill(getppid(), SIGKILL);
}
exit(EXIT_SUCCESS);
but the last child don't kill the father....
how can i do that ? i don't have any idea.
Your problem has been correctly diagnosed by Graeme Cole in a comment:
car_finished
, so the count in any child only ever reaches 1
, so if there is more than one child, the signal is never sent.How to resolve it?
You could use shared memory and place car_finished
in shared memory. However, you'd have to synchronize access to the shared memory between the processes, so this rapidly becomes unwieldy (assuming it was not deemed unwieldy when shared memory was mentioned).
It might be possible to use a file to contain the count of children. The children would use (advisory) locking on the file to prevent concurrent access, and each would decrement the count before it exits, and the one decreasing the count to zero would remove the file and send a signal to the parent process. This is pretty reliable, but not all that fast (but it is likely to be quite fast enough). The main problem occurs if a child exits without decrementing the count (e.g. because it crashes with a memory fault, or it is sent SIGKILL). Then the count will never go to zero, so the parent will never be signalled.
If the parent is simply waiting for the children to die, it should run in a wait()
loop:
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
/* …optionally… */
printf("%d: PID %d exited with status 0x.4X\n", (int)getpid(), corpse, status);
}
exit(EXIT_SUCCESS);
If the parent is doing some processing, the child should not send SIGKILL; it gives the parent no time to clean up. Each child could send the parent a SIGUSR1 signal, and the parent's signal handler could count the number of signals received, and exit when it has received them all. This is fiddlier to demonstrate in full, but uses sigaction()
to set up the signal handler.
Sometimes, the parent can create a pipe, close the write end, and attempt to read from it. The children would each close the read end of the pipe as it starts (code hygiene — this could be omitted). When the child is done, it exits, explicitly or implicitly closing the write end of the pipe. The parent will get a 'zero bytes read' return from the read()
when the last child exits, and can close the pipe (or just terminate).
These last solutions rely on the cooperation of the parent process. That's usually a safe bet (unless a family is dysfunctional, a parent helps their children as much as possible).