title: cleaning child processes with handler with waitpid pselect fork sigaction
body: <p>I have a server that receives messages into a socket and for each message received, do a fork exec. This part seems to be working properly.</p>
  
  <p>But I need to do this in non-blocking mode, so I've created a handler to clean properly all the terminated child processes with <code>waitpid()</code> ( as explained in many topics in forums ).</p>
  
  <p>the problem is that this handler generates an Interrupted system call to my <code>pselect</code> command and it stops the program with the following message:<br>
  <code>"select(): Interrupted system call"</code></p>
  
  <p>I found some explanations of this problem in forums with "Preventing race conditions" and so on, so I've tried to use <code>sigprocmask()</code> to block several signals, but it didn't work.</p>
  
  <p>I'm sure this is a trivial problem, but this is my first use of this kind of program.</p>
  
  <p>I would need some help.
  thanks in advance.</p>
  
  <p>Here is the program :</p>
  
  <pre><code>void
  clean_up_child_process (int signal_number)
  {
  
    pid_t p;
    int status;
  
    while (1)
      {
        p = waitpid (-1, &amp;status, WNOHANG);
  
        if (p == -1)
          {
            if (errno == EINTR)
              {
                continue;
              }
            break;
          }
        else if (p == 0)
          {
            break;
          }
      }
  
  
  }
  
  static void
  app (void)
  {
    SOCKET sock;
    char commande[BUF_SIZE];
    char res_cmd[BUF_SIZE];
    int max;
    int n;
  
    sock = init_connection ();
    max = sock;
    fd_set rdfs;
  
    sigemptyset (&amp;sigmask);
    sigaddset (&amp;sigmask, SIGCHLD);
    sigaddset (&amp;sigmask, SIGINT);
    sigaddset (&amp;sigmask, SIGTSTP);
    sigaddset (&amp;sigmask, SIGTERM);
    sigprocmask (SIG_BLOCK, &amp;sigmask, NULL);
  
    struct sigaction sigchld_action;
    memset (&amp;sigchld_action, 0, sizeof (sigchld_action));
    sigchld_action.sa_handler = &amp;clean_up_child_process;
    sigaction (SIGCHLD, &amp;sigchld_action, NULL);
  
    while (1)
      {
        int i = 0;
        FD_ZERO (&amp;rdfs);
  
        /* add STDIN_FILENO */
        FD_SET (STDIN_FILENO, &amp;rdfs);
  
        /* add the connection socket */
        FD_SET (sock, &amp;rdfs);
  
        sigemptyset (&amp;empty_mask);
        if (pselect (max + 1, &amp;rdfs, NULL, NULL, NULL, &amp;empty_mask) == -1)
          if (errno != EINTR)
            {
              perror ("select()");
              exit (errno);
            }
  
        if (FD_ISSET (STDIN_FILENO, &amp;rdfs))
          {
            /* stop process when type on keyboard */
            // break; must be disable to avoid bad exits
          }
        else if (FD_ISSET (sock, &amp;rdfs))
          {
            /* new client */
            SOCKADDR_IN csin = { 0 };
            size_t sinsize = sizeof csin;
            int csock = accept (sock, (SOCKADDR *) &amp; csin, &amp;sinsize);
            if (csock == SOCKET_ERROR)
              {
                perror ("accept()");
                continue;
              }
  
            if ((n = recv (csock, commande, BUF_SIZE - 1, 0)) &lt; 0)
              {
                perror ("recv(commande)");
                n = 0;
                continue;
              }
            commande[n] = 0;
            if ((n = fork ()) == -1)
              perror ("fork()");
            else if (n == 0)
              {
                close (STDOUT_FILENO);
                dup (csock);
                close (STDERR_FILENO);
                dup (csock);
                execlp (commande, commande, 0);
              }
            else
              {
                closesocket (csock);
              }
          }
      }
    end_connection (sock);
  }
  </code></pre>