Hi everyone,

This is a followup to a previous question about a fork/DBI clash.  I have a 
script that calls fork, which starts children which call some batch files, 
which call some perl scripts.  This works great (on Windows 2000).

However, when I try to connect to the database in this main script, just to 
get a number from a table to use in naming the batch files later, I get "The 
memory could not be read" pop-up error.  I disconnect from the database 
before I start the fork, and I only make that one connection.  However, it 
seems like whenever I try to have fork and DBI in the same script, it causes 
crashing.

In the following script I have commented out the DBI parts, and it works 
that way.  If these sections are un-commented, the script fails.

Any insights would be greatly appreciated.

Thanks!
Becka Louden


#!C:/Perl

# USE STATEMENTS

use Net::SMTP; # for sendmail
use File::Copy;
use DBI;
use Net::Time;
use Mail::Sender; # for sendmail
use POSIX ":sys_wait_h";
use Win32::Process;
use strict;

# GLOBALS

my $from         = "Collectamerica_automated_process\@collectamerica.com";
my $to           = "rlouden\@collectamerica.com";
my $thisfile      = "fork.pl";
my $dbname = 'dbi:Oracle:mydatabase';
my $user   = 'mylogin';
my $pass   = 'mypassword';
my $wait   = 0;


# SUB ROUTINES

sub ErrorReport{
        # used for win32::Process error handling
  print "Aha!: ", Win32::FormatMessage( Win32::GetLastError() );
}

sub sendmail{
        #sends mail in case of error
  #print "Arguments passed: @_\n";
    my($to, $from, $subject, @body) = @_;

    my $relay = "mail.collectamerica.com";
    my $smtp = Net::SMTP->new($relay,
                  Hello => 'WORKGROUP'); # specify mail domain);
    die "Could not open connection: $!" if (!defined $smtp);

    $smtp->mail($from);
    $smtp->to($to);

    $smtp->data();
    $smtp->datasend("To: $to\n");
    $smtp->datasend("From: $from\n");
    $smtp->datasend("Subject: $subject\n");
    $smtp->datasend("\n");
    foreach(@body) {
      $smtp->datasend(":$_\n");
    }
    $smtp->dataend();
    $smtp->quit;
}

sub get_max_cacv {
        #retrieves number of highest note from database
        my $cacv_max;
        my $max;

        $Main::get_num_cacv->execute();
        while(my $cacv_one = $Main::get_num_cacv->fetchrow_array) {
                $cacv_max = $cacv_one;
        }

        if($cacv_max =~ m/^CACV(\d{3})\/.*$/) {
                $max = $1;
        }

        return $max;
}

sub parent_proc {
        # Does nothing, just has children

  return 0;
}

sub child_proc {
        #calls batch file of number specified by argument
  my $args = (@_);
        if ($args != 1) {
                die "Whoops, wrong num args passed to fork_off\n";
        } else {
                my $num = $_[0];
                print "Child was called!: ";

                my $args = '';
                my $proc_obj = '';
                my $exitcode = -1;

                print "Attempting to open query${num}.bat\n";

                Win32::Process::Create($proc_obj,
                                                        
"c:/perl/exercises/fork/query${num}.bat",
                                                        $args,
                                                        0,
                                                        NORMAL_PRIORITY_CLASS,
                                                        ".")|| die( &ErrorReport() );

                $proc_obj->Wait(600000);
                $proc_obj->GetExitCode($exitcode);
                if($exitcode != 1) {
                print "Batch process exit code: $exitcode!\n";
                }

                return $exitcode;
        } # end else args = 1
}

sub fork_off {
  # fork processes so they run in parallel
  my $child = 0;
  my $parent = 0;
  my $pid;
  my $args = (@_);
  if ($args != 1) {
        die "Whoops, wrong num args passed to fork_off\n";
  } else {
          my $num = $_[0];

          if(defined($pid = fork)) {
                 if ($pid) {
                        print "Calling parent: $pid\n";
                        $parent = &parent_proc();

                 } else {
                        print "Calling child: $pid\n";
                        $child = &child_proc($num);
                        print "Child returned $child\n";
                        exit;
                 }
          } else {
                 print "Forking didn't work\n";
          }
          return $num;
        } # end else args = 1

  return 0;
}

sub reaper {
  print "In reaper.\n";
  my $zombie;
  our %Kid_Status;

  while ( ($zombie = waitpid(-1, WNOHANG)) == -1) {
    $Kid_Status{$zombie} = $?;
  }
}

#  DATABASE CONNECTION

if(0) { # MULTI LINE COMMENT

        my $subject = "Connection to database failed!";
        my @body = ("$thisfile failed to connect to database - please see log 
file\n");

        my $dbh;

        until (defined($dbh) || ($wait > 10) ) {

                $dbh    = DBI->connect($dbname, $user, $pass, {AutoCommit=>0})
                                                        || 
sendmail($to,$from,$subject,@body);
                if(!defined($dbh)) {
                        sleep 300;
                        $wait++;
                }
        } # end until (defined($dbh))

        if(!defined($dbh)) {
                die "$subject";
        }

        $dbh->{LongReadLen} = 214748363;
        $dbh->{LongTruncOk} = 1;
} # END MULTI LINE COMMENT

#  PREDEFINE STATEMENTS

#$Main::get_num_cacv            =       $dbh->prepare("SELECT frw_name from frw where
#                                                       frw_name LIKE 'CACV%'");


#  MAIN

my @num_month = 
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36);

# GET CACV NUMBER FROM DATABASE DYNAMICALLY
#my $max_month = &get_max_cacv();
#my @num_month = (1..$max_month);

#print "Num_month is @num_month\n";

#$Main::get_num_cacv-> finish();

#$dbh->disconnect or warn "Disconnection failed: $DBI::errstr\n";

foreach my $num (@num_month) {
        # write the batch files to run the pl files

        open(BATFILE, ">c:/perl/exercises/fork/query${num}.bat") || die "I can't 
open ${num}.bat\n";
        print BATFILE "c:/perl/exercises/fork/query${num}.pl\n";
        close(BATFILE);

        open(PLFILE, ">c:/perl/exercises/fork/query${num}.pl") || die "I can't open 
${num}.pl\n";
        print PLFILE "#!C:/Perl\n#Perl stub file\n",
                "print \"File query${num}.pl was called successfully!\n\";";
        close(PLFILE);
}


# call the batch files thru FORK
our $zombies = 0;
my @processes = ();
{ # scope bracket
  $SIG{CHLD} = sub {$zombies++};
  foreach my $num (@num_month) {

    my $done = &fork_off($num);
    print "Done: $done\n";
  }

&reaper() && ($zombies = 0) if $zombies;

} # end scope bracket

print "Done with all.\n";





_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com

Reply via email to