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

Reply via email to