LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-07-2009, 02:08 AM   #1
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Rep: Reputation: 0
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
 
Old 02-07-2009, 05:49 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
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 ?
 
Old 02-07-2009, 10:11 PM   #3
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Original Poster
Rep: Reputation: 0
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

Last edited by murahman; 02-07-2009 at 10:12 PM.
 
Old 02-08-2009, 04:45 AM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by murahman View Post
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 ?
 
Old 02-08-2009, 05:20 AM   #5
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Original Poster
Rep: Reputation: 0
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
 
Old 02-08-2009, 05:28 AM   #6
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Original Poster
Rep: Reputation: 0
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
 
Old 02-08-2009, 06:09 AM   #7
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by murahman View Post
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 ?
 
Old 02-08-2009, 06:17 AM   #8
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Original Poster
Rep: Reputation: 0
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
 
Old 02-08-2009, 06:23 AM   #9
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
I think you still don't have

Code:
use strict;
in your code.
 
Old 02-08-2009, 06:58 AM   #10
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Original Poster
Rep: Reputation: 0
i tried using strict but its causing the same problem.
 
Old 02-09-2009, 03:27 AM   #11
murahman
LQ Newbie
 
Registered: Jul 2008
Posts: 20

Original Poster
Rep: Reputation: 0
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
 
Old 02-10-2009, 10:58 AM   #12
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple Perl Sockets + Child Processes (fork) Reion Programming 3 10-13-2008 06:17 PM
Many complications after crashing first install and crashing and reinstalling several dong Linux - Newbie 1 10-06-2008 04:33 AM
perl - using fork davidcollins001 Programming 7 11-14-2007 02:27 AM
fork() in c++ deveraux83 Programming 5 11-13-2004 03:12 PM
perl(Cwd) perl(File::Basename) perl(File::Copy) perl(strict)....What are those? Baldorg Linux - Software 1 11-09-2003 08:09 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:18 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration