views:

121

answers:

2

So when I run this code it seems to fork bomb the system can you guys help me out? All I want to do is start a thread for each one of the appWatch domains and enviroments.

#!/usr/bin/perl
#
#
#       Starts the mass processes to watch each directory & enviroment.
#
#
#
###################################################################################
use strict;
use warnings;
use POSIX 'setsid';
setsid();
my @domains = (qw(austin batman luke heman drevil joker skeltor drevil goodguy badguy));
my @envs = (qw(qa dev));
        foreach my $env (@envs){
                foreach my $guy (@domains){
                        unless(my $pid = fork()){
                                system("echo $env.$guy");
                                system("sleep 10 ");
                                #system("./appWatch -d $guy -e $env");
                                open PID, ">>pid.lock";
                                print PID $$ . "\n";
                                print "$$ is Parent, $pid is child";
                }
        }
}
                wait();
+2  A: 

With

$ cat appWatch 
#! /usr/bin/perl -l
print "[", join("][" => @ARGV), "]";

running on

$ uname -a
Linux mybox 2.6.32-24-generic #39-Ubuntu SMP Wed Jul 28 05:14:15 UTC 2010 x86_64 GNU/Linux

I get no fork bomb, just an unexciting Cartesian product:

$ ./prog.pl 
[-d][domains][-e][enviromentA]
[-d][domains][-e][enviromentB]
Greg Bacon
If I get the system up that I just forked I will show you the latest code. Its essentially just that. IT normally doesnt but for some reason it starts thousands of processes
Nerdatastic
+3  A: 

Your code should only create three children. If you are seeing a bunch of children being created then you are running different code (or the culprit is appWatch not your code). On a slightly unrelated note, there are a couple things you should probably be doing differently:

  1. fork has three possible return values, not two
  2. you must reap your children or set the system up to reap them for you
  3. you should use exec instead of system if you don't want to return to the code
  4. you should use the multiple argument version of system and exec instead of the one argument version if you don't want the shell to do stuff with the arguments.

Here is my version of your code:

$SIG{CHLD}  = "IGNORE"; #auto-reap the children
my @domains = qw(domains);
my @envs    = qw(enviromentA enviromentB);
for my $env (@envs){
        for my $guy (@domains){
                die "could not fork: $!" unless defined(my $pid = fork);
                next if $pid;
                exec "./appWatch", "-d", $guy, "-e", $env;
                die "exec must have failed";
        }
}

You updated version of the code shows what happened. Your child does not exit. Here is how I would write your code:

#!/usr/bin/perl
# Starts the mass processes to watch each directory & enviroment.

use strict;
use warnings;
use POSIX 'setsid';
setsid();

my @domains = qw(
    austin  batman luke    heman
    drevil  joker  skeltor drevil
    goodguy badguy
);
my @envs = qw(qa dev);

my @pids;
for my $env (@envs){
    for my $guy (@domains){
        die "could not fork: $!" unless defined(my $pid = fork);
        if ($pid) {
            push @pids, $pid;
            next;
        }
        print "$env.$guy\n";
        sleep 10; #FIXME: I don't know if you really need this
        #exec will replace the child process with appWatch
        exec "./appWatch", "-d", $guy, "-e", $env;
        die "exec failed for some reason";
    }
}
for my $pid (@pids) {
    waitpid $pid, 0;
}
Chas. Owens
Ok Cool once I get the system back up I will post the bad code but yours works great. Thanks! My second question if you could, how do I make it so that if this script gets killed it kills all of its children?
Nerdatastic
@Nerdatastic Off the top of my head, you could remember all of the child IPs in an array and use an `END` block to `kill` them: `END { kill 15, @pids }`.
Chas. Owens
I just updated the code with the one that crashed the system I am usuing your modified solution for now.
Nerdatastic
Wow thank you so much!!
Nerdatastic
@Nerdatastic I just noticed that you are in NoVA. Have you considered going to the DC Perl Mongers meeting? It is on the first Tuesday of every month and is literally just above the Farragut West metro stop (http://dc.pm.org/).
Chas. Owens
@Chas, I had no idea but it looks interesting I will def look into it!
Nerdatastic