Defunct ("zombie") processes arise when the respective process has terminated, but its (still alive) parent hasn't reaped the child's status by waiting for it.
When you modify check.pl as follows
#!/usr/bin/perl
use POSIX ":sys_wait_h";
print "process id: $$\n";
my $pid = fork;
my $FH;
unless($pid){
setpgrp;
exec('./script');
}
print "Child process id is: $pid\n";
for (1..5) {
kill -9, $pid if $_ == 4; # kill children in the 4th round
system "ps Tf -o etime,pid,pgrp,stat,cmd";
sleep(3);
waitpid(-1, WNOHANG);
}
you'll get something like
$ ./check.pl
process id: 4609
Child process id is: 4610
ELAPSED PID PGRP STAT CMD
06:17 4569 4569 Ss bash
00:00 4609 4609 S+ \_ /usr/bin/perl ./check.pl
00:00 4610 4610 R \_ /usr/bin/perl ./script
00:00 4611 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd
I am running
I am running
I am child and I'am running
I am running
ELAPSED PID PGRP STAT CMD
06:20 4569 4569 Ss bash
00:03 4609 4609 S+ \_ /usr/bin/perl ./check.pl
00:03 4610 4610 R \_ /usr/bin/perl ./script
00:02 4612 4610 S | \_ /usr/bin/perl ./script
00:01 4613 4610 S | \_ /usr/bin/perl ./script
00:00 4614 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd
I am child and I'am running
I am running
I am child and I'am running
I am child and I'am running
I am running
I am child and I'am running
I am child and I'am running
I am running
ELAPSED PID PGRP STAT CMD
06:23 4569 4569 Ss bash
00:06 4609 4609 S+ \_ /usr/bin/perl ./check.pl
00:06 4610 4610 S \_ /usr/bin/perl ./script
00:05 4612 4610 S | \_ /usr/bin/perl ./script
00:04 4613 4610 S | \_ /usr/bin/perl ./script
00:03 4615 4610 S | \_ /usr/bin/perl ./script
00:02 4616 4610 S | \_ /usr/bin/perl ./script
00:01 4617 4610 S | \_ /usr/bin/perl ./script
00:00 4618 4610 S | \_ /usr/bin/perl ./script
00:00 4619 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd
I am child and I'am running
I am child and I'am running
I am child and I'am running
I am running
I am child and I'am running
I am child and I'am running
I am child and I'am running
I am running
I am child and I'am running
I am child and I'am running
I am child and I'am running
I am child and I'am running
I am running
ELAPSED PID PGRP STAT CMD
06:26 4569 4569 Ss bash
00:09 4609 4609 S+ \_ /usr/bin/perl ./check.pl
00:09 4610 4610 Z \_ [script] <defunct>
00:00 4623 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd
ELAPSED PID PGRP STAT CMD
06:29 4569 4569 Ss bash
00:12 4609 4609 S+ \_ /usr/bin/perl ./check.pl
00:00 4624 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd
As you can see in the next-to-last ps output, all children have been killed, but the script process is defunct, because its parent hasn't yet gotten around to reaping it (due to how I deliberately wrote the loop). Three secs later, in the last ps output, the process is no longer there, because waitpid has been called in the meantime. |