简体   繁体   中英

Why do I get more than one SIGCHLD when I only called fork once?

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 ?

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.)

  1. system("ps -lH"); will call fork() too, see http://man7.org/linux/man-pages/man3/system.3.html

  2. 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM