0

I have to kill/clean a zombie process in linux C. All I know is the PID of the zombie.

I'm creating a few zombie processes in a loop:

int i = 0;
for (i; i<5; i++)
{
  system("(: & exec sleep 30) &"); // create zombie for 30 sec
}

I can get their PID number using:

system("ps aux | awk '{ print $8 " " $2 }' | grep -w Z");

But how to kill/clean them using just the PID? I'm saving the PID in a variable and standard signal:

kill(PID,9) 

Doesn't even work, because the process is dead already. Any other way to achieve it? Please don't ask me why the hell I'm creating zombies to kill them later. It's not the case.

Junuxx
  • 14,011
  • 5
  • 41
  • 71
krzakov
  • 3,871
  • 11
  • 37
  • 52

5 Answers5

3

A "zombie" is a process that is already dead. You can't kill it again.

A "zombie" is actually just an entry in the process table containing the exit status of the process. To get rid of it, the parent process has to call wait() to retrieve that information. Alternatively the parent process can exit itself; then the child becomes a so called "orphan" and gets adopted by init, the process with ID 1. init automatically reaps all dead children.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • But how to do it. I dont have a parent PID. I'm using bash to create zombies. – krzakov Dec 02 '12 at 13:24
  • Why don't you simply stop creating zombies in the first place? – melpomene Dec 02 '12 at 13:24
  • Because my client want to have them. That's little messy but I have to create a delete them. – krzakov Dec 02 '12 at 13:27
  • Please read end of first question :) – krzakov Dec 02 '12 at 13:32
  • I'm not asking for fun. This information actually determines the solution you're going to get (because right now it's rather unclear what the problem actually is). – melpomene Dec 02 '12 at 13:34
  • All I have to do is create a specific number of zombies (that's why i use loop for that) then I have to figure it out how to kill zombie (one of them) using his PID. – krzakov Dec 02 '12 at 13:38
  • Client want's this. Doesn't really matter. – krzakov Dec 02 '12 at 13:42
  • The client can want until they're blue in the face – they can't get what's not possible. The only way those zombies are going away is if their exit status is reaped, and if the parent doesn't do that, then they'll hang around until the parent dies, and init reaps them. It sounds like you're going to have to step back and find another approach to the underlying problem. – Norman Gray Dec 02 '12 at 13:53
3

Here is a script I created to kill ALL zombie processes. It uses the GDB debugger to attach to the parent process and send a waitpid to kill the zombie process. This will leave the parent live and only slay the zombie.

GDB debugger will need to be installed and you will need to be logged in with permissions to attach to a process. This has been tested on Centos 6.3

#!/bin/bash
##################################################################
# Script: Zombie Slayer
# Author: Mitch Milner
# Date:   03/13/2013 ---> A good day to slay zombies
#
# Requirements: yum install gdb
#               permissions to attach to the parent process
#
# This script works by using a debugger to
# attach to the parent process and then issuing
# a waitpid to the dead zombie. This will not kill
# the living parent process.
##################################################################

clear
# Wait for user input to proceed, give user a chance to cancel script
echo "***********************************************************"
echo -e "This script will terminate all zombie process."
echo -e "Press [ENTER] to continue or [CTRL] + C to cancel:"
echo "***********************************************************"
read cmd_string
echo -e "\n"

# initialize variables
intcount=0
lastparentid=0

# remove old gdb command file
rm -f /tmp/zombie_slayer.txt

# create the gdb command file
echo "***********************************************************"
echo "Creating command file..."
echo "***********************************************************"
ps -e -o ppid,pid,stat,command | grep Z | sort | while read LINE; do
  intcount=$((intcount+1))
  parentid=`echo $LINE | awk '{print $1}'`
  zombieid=`echo $LINE | awk '{print $2}'`
  verifyzombie=`echo $LINE | awk '{print $3}'`

  # make sure this is a zombie file and we are not getting a Z from
  # the command field of the ps -e -o ppid,pid,stat,command
  if [ "$verifyzombie" == "Z" ]
  then
    if [ "$parentid" != "$lastparentid" ]
    then
      if [ "$lastparentid" != "0" ]
      then
        echo "detach" >> /tmp/zombie_slayer.txt
      fi
    echo "attach $parentid" >> /tmp/zombie_slayer.txt
    fi
    echo "call waitpid ($zombieid,0,0)" >> /tmp/zombie_slayer.txt
    echo "Logging: Parent: $parentid  Zombie: $zombieid"
    lastparentid=$parentid
  fi
done
if [ "$lastparentid" != "0" ]
then
  echo "detach" >> /tmp/zombie_slayer.txt
fi

# Slay the zombies with gdb and the created command file
echo -e "\n\n"
echo "***********************************************************"
echo "Slaying zombie processes..."
echo "***********************************************************"
gdb -batch -x /tmp/zombie_slayer.txt
echo -e "\n\n"
echo "***********************************************************"
echo "Script complete."
echo "***********************************************************"

Enjoy.

  • 1
    If you can post *exactly* the same answer to two questions then it's a sign that the questions are duplicates. Rather than post a second answer you should flag (or vote) to close as a duplicate. – ChrisF Mar 14 '13 at 22:35
2

You're correct that you can't kill zombies because they're already dead.

The reason they're zombies is because the process has finished but the parent has not harvested the exit code.

Eventually, init should do this for you if and when the zombie becomes an orphan. A true zombie, a process that still has a parent but that parent has yet to harvest the exit code, will persist until either:

  • the parent does harvest the exit code; or
  • it becomes an orphan when the parent exits.
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

What you are doing seems quite twisted. I am going to assume you have tried to create a minimal test case to show a broader problem and answer anyway - A zombie is created when a feather process does not clean (calls waitpid and friends) its child process resources.

So, either write the father process code correctly to respond to SIGCHLD and calling waitpid or, if you have no control over the father process, as I am guessing is the case here, kill the father process (send SIGTERM to the father).

The reason the latter will work is that all fatherless children are re-parented to init (PID 1) that will perform the needed clean up.

gby
  • 14,900
  • 40
  • 57
0

You can try using the SIGCHLD signal.For eg in C:

signal(SIGCHLD, handleSIGCHLD);


  void handleSIGCHLD(int signum) {
  int stat;

 /*Kills all the zombie processes*/
  while(waitpid(-1, &stat, WNOHANG) > 0);
}
Fyre
  • 1,180
  • 8
  • 12