LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   perl crashing after doing some fork() (https://www.linuxquestions.org/questions/programming-9/perl-crashing-after-doing-some-fork-702892/)

murahman 02-07-2009 02:08 AM

perl crashing after doing some fork()
 
Hello everyone,
I have a perl program that does the following thing:
1. Continuously looking in a mysql database table for a row that has status '2'.
2. If a status 2 row is found it first checks whether that particular row has been previously visited or not.
3. If not previously visited it will create a child process.
4. The parent again enters the loop and look for any new status '2'.
5. In the mean time the child process waits for 10 sec and updates the row status to 7 if the status of that row is still remaining as '2'.

This program works fine for sometime but after some time it simply crashes. Can you please help me out!!!! Here is my code:

Code:

#!/usr/bin/perl
use DBI;
use Time::Local;
use POSIX ":sys_wait_h";

$SIG{CHLD} = sub {wait ()};

#$num = "10";
my @childs;
#my $m = "mishu";

#pipe (B_IN, B_OUT);
#my $pid2 = fork();


  ###################### DATABASE CONNECTION #########################
  my $dbName = "abc";
  my $userName = "root";
  my $password = "";
  my $dbpath = "dbi:mysql:database=$dbName;host=localhost";
  my $dbh = DBI->connect($dbpath, $userName, $password) or die "Can't open database: $DBI::errstr";
  #####################################################################

  my %alreadyVisited;
  my $messageID;

  while(1)
  {
      my $query = "SELECT * FROM `transaction_log` WHERE status = '2'";
      my $qh = $dbh->prepare($query);
      $qh->execute();

      while(my $row = $qh->fetchrow_hashref())
      {
        $messageID = $row->{message_id};

        if(exists $alreadyVisited{$messageID})
        {
            #print $messageID." already exists in HASH \n";
            next;
        }
        else
        {
            #print $messageID." is a new one \n";
        }

        my $pid = fork();

        if($pid)
        {
            #parent
            #print "Child created with PID : ".$pid."\n";
            push(@childs, $pid);
        }
        elsif($pid == 0)
        {
            #child
            print $messageID."  is in child\n";
            sleep(10);
            updateStatus($messageID);
            #print "%%%%%%%%%%%%%%%%%%%%%%%%%%        \n";
            exit(0);
        }
        else
        {
            print "Could not fork \n";
        }
        $alreadyVisited{$messageID} = $row->{name};
      }
      sleep(1);
     
      foreach (@childs)
      {
        waitpid($_, WNOHANG);
      }
  }

  print "LAST MSG ID is : ".$messageID."\n";

  if($dbh->disconnect())
  {
      print "hello \n";
  }
  print "going to terminate child one \n";
  #exit(0);

sub updateStatus
{
  ###################### DATABASE CONNECTION #########################
  my $dbName = "abc";
  my $userName = "root";
  my $password = "";
  my $dbpath = "dbi:mysql:database=$dbName;host=localhost";
  my $dbh2 = DBI->connect($dbpath, $userName, $password) or die "Can't open database: $DBI::errstr";
  #####################################################################

  my $ID = $_[0];

  print $ID."****\n";
  my $query2 = "UPDATE `transaction_log` SET status = '7' WHERE status = '2' AND message_id = '".$ID."'";
  my $qh2 = $dbh2->prepare($query2);
  if($qh2->execute() eq 1)
  {
      print $ID." has been updated to 7\n";
  }
  else
  {
      print "Failed to update ID is : ".$ID."\n";
  }


  $dbh2->disconnect();
}

Please help me out guys.

Thanks
Mishu

Sergei Steshenko 02-07-2009 05:49 AM

First add

Code:

use strict;
use warnings;

just after

Code:

#!/usr/bin/perl
and make sure there are no error and warning messages during compilation and run.

The word "crashes" is not clear in this context - what is the exact error message ?

murahman 02-07-2009 10:11 PM

Actually there is no error message. you can see that i am running an infinite while loop. So it is not supposed to stop. But it stops after some time. I am using the word "Perl crashing". Because before stopping a windows prompt appears saying "perl.exe Application error. The instruction at '0x.........' referenced memory at '0x........' The memory could not be read."

There is also another error saying "DESTROY ignored because DBI sth handle (DBD::mysql::st) is owned by thread 2
33fac not current thread 45ad004" But this error msg does not come all the time


Please help me out guys

Mishu

Sergei Steshenko 02-08-2009 04:45 AM

Quote:

Originally Posted by murahman (Post 3435735)
Actually there is no error message. you can see that i am running an infinite while loop. So it is not supposed to stop. But it stops after some time. I am using the word "Perl crashing". Because before stopping a windows prompt appears saying "perl.exe Application error. The instruction at '0x.........' referenced memory at '0x........' The memory could not be read."

There is also another error saying "DESTROY ignored because DBI sth handle (DBD::mysql::st) is owned by thread 2
33fac not current thread 45ad004" But this error msg does not come all the time


Please help me out guys

Mishu

Do I understand correctly that a number of children is created by your program and if all the children are alive and well then your program should iterate in some kind of loop indefinitely ?

murahman 02-08-2009 05:20 AM

Thank you Seregi for your reply. Actually I am iterating in an infinite while loop where i am checking in the database table for status '2' and if i find any new entry i simply fork. In the child process it waits for 10 sec and after 10 sec it calls a function 'updateStatus' which simply updates the status '2' to '7'(if the status is still 2). Parallely the parent process will go in the loop again and check if there is any new row inserted with status '2'.

Basically I am trying to make a timer function that will keep track of any new row being inserted in the DB and after a certain time later, it will update that row.

Thanks
Mishu

murahman 02-08-2009 05:28 AM

actually I have just updated the code a bit. Please have a look guys:

<code>
#!/usr/bin/perl
use DBI;
use Time::Local;
use POSIX ":sys_wait_h";
use warnings;

$SIG{CHLD} = sub {wait ()};
my @childs;

###################### DATABASE CONNECTION #########################
my $dbName = "middleware";
my $userName = "root";
my $password = "";
my $dbpath = "dbi:mysql:database=$dbName;host=localhost";
my $dbh = DBI->connect($dbpath, $userName, $password) or die "Can't open database: $DBI::errstr";
#####################################################################

my %alreadyVisited;
my $messageID;

while(1)
{
my $query = "SELECT * FROM `transaction_log` WHERE status = '2'";
my $qh = $dbh->prepare($query);
$qh->execute();

while(my $row = $qh->fetchrow_hashref())
{
$messageID = $row->{message_id};

if(exists $alreadyVisited{$messageID})
{
#print $messageID." already exists in HASH \n";
next;
}
else
{
#print $messageID." is a new one \n";
}

my $pid = fork();

if($pid)
{
#parent
#print "Child created with PID : ".$pid."\n";
push(@childs, $pid."~".$messageID);
}
elsif($pid == 0)
{
#child
print $messageID." is in child\n";
sleep(10);
updateStatus($messageID);
#print "%%%%%%%%%%%%%%%%%%%%%%%%%% \n";
exit(0);
}
else
{
print "Could not fork \n";
}
$alreadyVisited{$messageID} = $row->{name};
}
sleep(1);

foreach (@childs)
{
print "**".$_."**\n";
if($_ ne "")
{
my @pidArray = split('~', $_);
my $pid = $pidArray[0];
my $mid = $pidArray[1];
#print $pid." ".$mid."++++\n\n";
if(waitpid($pid, WNOHANG) eq $pid)
{
my $element = $pid."~".$mid;
my( $index )= grep { $childs[$_] eq $element } 0..$#childs;
splice(@childs, $index, 1);
}
}
}
}

print "LAST MSG ID is : ".$messageID."\n";

if($dbh->disconnect())
{
print "hello \n";
}
print "going to terminate child one \n";

sub updateStatus
{
###################### DATABASE CONNECTION #########################
my $dbName = "middleware";
my $userName = "root";
my $password = "";
my $dbpath = "dbi:mysql:database=$dbName;host=localhost";
my $dbh2 = DBI->connect($dbpath, $userName, $password) or die "Can't open database: $DBI::errstr";
#####################################################################

my $ID = $_[0];

print $ID."****\n";
my $query2 = "UPDATE `transaction_log` SET status = '7' WHERE status = '2' AND message_id = '".$ID."'";
my $qh2 = $dbh2->prepare($query2);
if($qh2->execute() eq 1)
{
print $ID." has been updated to 7\n";
}
else
{
print "Failed to update ID is : ".$ID."\n";
}


#$dbh2->commit;
$dbh2->disconnect();
}
</code>

thnx
mishu

Sergei Steshenko 02-08-2009 06:09 AM

Quote:

Originally Posted by murahman (Post 3435941)
Thank you Seregi for your reply. Actually I am iterating in an infinite while loop where i am checking in the database table for status '2' and if i find any new entry i simply fork. In the child process it waits for 10 sec and after 10 sec it calls a function 'updateStatus' which simply updates the status '2' to '7'(if the status is still 2). Parallely the parent process will go in the loop again and check if there is any new row inserted with status '2'.

Basically I am trying to make a timer function that will keep track of any new row being inserted in the DB and after a certain time later, it will update that row.

Thanks
Mishu

My point/question was: is your main program supposed to "crash" in case one of its children exits ?

If yes, maybe you should check what is happening with(in) each child ?

murahman 02-08-2009 06:17 AM

No my main program is not supposed to crash. Every time a child is created it will exit after 10 sec(by doing/not doing a update in DB) anyway. The child programs that are being created are doing their job(updating row) properly as long its running fine. May be I am doing something wrong regarding creating child or something. I cant find a clue what actually is the problem that is actually causing a crash.
Thanks man
mishu

Sergei Steshenko 02-08-2009 06:23 AM

I think you still don't have

Code:

use strict;
in your code.

murahman 02-08-2009 06:58 AM

i tried using strict but its causing the same problem.

murahman 02-09-2009 03:27 AM

hello everyone, I am still facing the same problem. Please help me out guys. My project deadline is 2 days from now. I have to find some solution.
Thanks mishu

theNbomr 02-10-2009 10:58 AM

Since your program is apparently running under Windows, this may not apply, but if you are constantly spawning child processes without calling wait() to reap them, it seems possible that you are filling the process table (or whatever is equivalent under Windows). In Unixish OS's this is the standard paradigm to prevent zombie processes.

--- rod.


All times are GMT -5. The time now is 12:31 PM.