Reputation: 2072
i'm studying signals in Linux and i'm trying to understand the mechanisms of processes. I Wrote this code :
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
void filsFini(int sig){
printf("The Child finished\n");
}
int main(){
pid_t pid;
system("clear");
if((pid=fork())==0){
printf("Child in a break\n");
for(;;);
}
printf("The father %d \n",getpid());
system("ps -lH");
(void) signal(SIGCHLD,filsFini);
printf("hit a button to end\n");
getchar();
kill(pid,SIGINT);
system("ps -lH");
waitpid(pid,NULL,0);
system("ps -lH");
return EXIT_SUCCESS;
}
at the end i get this result which i have one problem is that the printf("Child finished\n");
is written twice how can i avoid that ?
Upvotes: 3
Views: 949
Reputation: 1498
system("ps -lH");
will call fork()
too, see http://man7.org/linux/man-pages/man3/system.3.html
If you want call printf("Child finished\n");
only once, you could catch SIGINT
in child process and output it.
The following code
could work:
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
void handle_SIGINT(int sig) {
printf("The Child finished\n");
exit(EXIT_FAILURE);
}
int main(){
signal(SIGINT, handle_SIGINT);
pid_t pid;
if ((pid=fork()) == 0) {
printf("Child in a break\n");
for(;;)
;
}
printf("The father %d \n", getpid());
system("ps -lH");
printf("hit a button to end\n");
getchar();
kill(pid, SIGINT);
printf("\nbefore waitpid:\n");
system("ps -lH");
waitpid(pid, NULL, 0);
printf("\nafter waitpid:\n");
system("ps -lH");
return EXIT_SUCCESS;
}
Upvotes: 1
Reputation: 140569
You are creating additional children with each call to system("ps -lH")
, and you get SIGCHLD
notifications for them too. Unfortunately, there isn't any way to control which child processes you receive SIGCHLD
notifications for. It's all or nothing.
For the program you have written, I would recommend you choose nothing: don't install a handler for SIGCHLD
. You can rely on the waitpid
call that you already have, to notify you when the child process you directly created has finished. system
will take care of calling waitpid
for the child processes it creates; you don't have to worry about them.
(The all-or-nothing nature of SIGCHLD
is a major hassle when writing more complicated programs that need to wait for variable combinations of child process completions and asynchronous I/O events, especially if there are libraries involved that might create child processes that the main event loop doesn't know about. But don't worry about that till you get there.)
Upvotes: 4