c++unixforkparent-childwaitpid

Zombie process is not cleanup with waitpid call


I am watching the processes with htop and I see that child process stays as zombie even though I clean up with waitpid call. Any idea why this might happen?

Thank you very much!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>

void child_signal_handler(int signal) {
  printf("Someone is stabbed me with signal %d\n", signal);
}

int main(int argc, char** argv)
{
  const pid_t child = fork();

  if (child == 0) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &child_signal_handler;
    sigaction(SIGTERM, &sa, NULL);
    printf("Child is started in busy loop\n");
    while (true)
      ;
  } else {
    const int mercy_period = 3;
    printf("Parent is angry and gonna kill his child in %d sec\n", mercy_period);
    sleep(mercy_period);
    kill(child, SIGTERM);
    // clean-up zombie child process as it is terminated before we can wait on
    // it
    int status = 0;
    while(waitpid(-1, &status, WNOHANG) > 0);
  }

  return EXIT_SUCCESS;
}

Solution

  • waitpid glibc implementation comments

    If PID is (pid_t) -1, match any process. If the WNOHANG bit is set in OPTIONS, and that child is not already dead, return (pid_t) 0.

    The while loop clearly exits immediately as 0 > 0 is false.

    Change the else and the signal to SIGKILL

    } else {
        const int mercy_period = 3;
        printf("Parent is angry and gonna kill his child in %d sec\n", mercy_period);
        sleep(mercy_period);
        kill(child, SIGKILL);
     
        int status = 0;
        pid_t pid = waitpid(-1, &status, WNOHANG);
        while(!pid) {
            pid = waitpid(-1, &status, WNOHANG);
            printf("%d\n", pid);    
        }
    }
    

    After few attempts waitpid will return the pid of the child process. A success.

    enter image description here