Hello and good afternoon,
: I'm looking for some examples of bad coding.
You may have come to the right store. Well, anyway, I'm happy to
place my own bad coding examples on display here.
: Specifically programs that ignore their children (creating zombie
: processes) and that do not exit cleanly (creating orphans) for
: init to adopt.
Why are there so many angry teenagers in the world, bent on becoming
zombies? While I'm not crazy about the Twilight series, I guess I
like a vampire-centric world a bit more than these pesky
parent-hating zombies.
You have two questions there. One question is about creating
zombies and the other is about orphans. They are two distinct
issues. The code below, should illustrate first abandonment:
$ perl zombie.pl abandon
I forked a kid (PID 3224) and abandoned it.
I hate my parent (PPID 3223)!
$ My parent abandoned me (PPID now 1)!
Note that the parent exits and we get a shell prompt back. Three
seconds later, the child reports its new parent and then exits.
This code also demonstrates zombification (two shells open to do
this):
$ perl zombie.pl zombie
I forked a kid (PID 3231) and plan on ignoring it.
I hate my parent (PID 3230)!
My parent is ignoring me--as retribution, I'm going to become a zombie as PID
3231.
Check the process table with 'ps w 3231', and you'll see that 3231 is a
zombie.
And, here's your zombie:
$ ps www 3231
PID TTY STAT TIME COMMAND
3231 pts/16 Z+ 0:00 [perl] <defunct>
OK, so what should you read to get a better handle on what's going
on here? My advice is to dig up a copy of 'Advanced Programming in
the Unix Environment' (APUE) by W. Richard Stevens and Stephen Rago
and read the first 8 or 9 sections of the Process Control chapter
(chapter 8).
I would note, as well, that process control and signal handling are
reasonably intertwined, so if you are going to dive into APUE, I'd
suggest reading the chapter on Signals (chapter 10), as well.
: Though that may sound like I know what I'm talking about I don't
: completely. I was asked during an interview about the kill
: command which led to getting rid of zombie process.
The kill command does not get rid of zombie processes--not when
applied to the zombies themselves, at any rate. You would have to
find the parent and send a signal to the parent to get it to either
A) reap its children or B) exit, thereby letting init do the job.
: I made a complete fool of myself with my answer (who frets about
: no-human zombies theses days?) so went a-lookin' and found the
: _right_ (more correct?) answer(s). Now I'd like to test them.
:
: The example code I've found so far has been pretty simplistic --
: create a bunch of zombie processes then exit cleanly, cleaning up
: after itself. Plus the program didn't run long enough to even
: test using 'kill -s SIGCHLD <ppid>'.
:
: Finally I'd like it to exit without cleaning up causing the
: zombie(s) to become an orphans.
Unless something is seriously broken on your system, or with your
init, or init replacement (runit, upstart, etc.), then your init
process should reap the zombies quite quickly after they become
orphaned.
Others may be able to provide more detail on why this is, or whether
this is uniformly the case across various *nix, but a child which
has been orphaned is typically inherited by process ID 1, a.k.a.
init.
-Martin
#! /usr/bin/perl
#
# -- Let's make a Zombie!
use POSIX;
sub abandon {
my $pid = fork();
die "Something went tilt: $!" if ! defined $pid;
if ($pid == 0) { # -- in the child
printf STDERR "I hate my parent (PPID %s)!\n", POSIX::getppid();
sleep(3);
printf STDERR "My parent abandoned me (PPID now %s)!\n",
POSIX::getppid();
} else { # -- in the parent
printf STDERR "I forked a kid (PID %s) and abandoned it.\n", $pid;
}
}
sub zombie {
my $pid = fork();
die "Something went tilt: $!" if ! defined $pid;
if ($pid == 0) { # -- in the child
printf STDERR "I hate my parent (PID %s)!\n", POSIX::getppid();
sleep(3);
my $ownpid = POSIX::getpid();
die "My parent is ignoring me--as retribution, I'm going to become a
zombie as PID $ownpid.\n";
} else { # -- in the parent
printf STDERR "I forked a kid (PID %s) and plan on ignoring it.\n",
$pid;
my $sigset = POSIX::SigSet->new(SIGINT, SIGSTOP, SIGHUP, SIGTERM,
SIGQUIT, SIGPIPE, SIGCHLD, SIGCLD);
sigprocmask(SIG_BLOCK, $sigset) or
die "Cannot ignore that damned child: $!";
sleep(4);
printf STDERR "Check the process table with 'ps w $pid', and you'll see
that $pid is a zombie.\n";
sleep(60);
}
}
if ( grep { 'abandon' eq $_ } @ARGV ) {
abandon();
} else {
zombie();
}
# -- end of file
--
Martin A. Brown
http://linux-ip.net/_______________________________________________
PLUG mailing list
[email protected]
http://lists.pdxlinux.org/mailman/listinfo/plug