Skip Menu |

This queue is for tickets about the DBD-mysql CPAN distribution.

Report information
The Basics
Id: 5135
Status: resolved
Priority: 0/
Queue: DBD-mysql

People
Owner: Nobody in particular
Requestors: dankney [...] network1.net
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 2.9002
  • 2.9003
Fixed in: (no value)



Subject: fork disrupts the database connection 2.9002 and 2.9003
Distribution names: DBD-MySQL-2.9002 and DBD-mysql-2.9003 Perl versions: 5.8.0 and 5.8.1 Operating systems: Linux cartman.network1.net 2.4.22-1.2115.nptl #1 Wed Oct 29 15:20:17 EST 2003 i586 i586 i386 GNU/Linux FreeBSD skipper.network1.net 4.8-RC FreeBSD 4.8-RC #0: Wed Mar 5 16:45:13 EST 2003 root@skipper.network1.net:/usr/obj/usr/src/sys/FNGi i386 After an initial select, and then a fork, the database connection still exists, but is unusable. That is as specific as I can be... Here is some example code that does not work under the above mentioned dbd versions, but does work on dbd-mysql-2.1026: #!/usr/bin/perl my $db_host='localhost'; my $db='fngimon'; my $db_user='<hidden>'; my $db_pass='<hidden>'; use strict; use DBI; use POSIX ":sys_wait_h"; my $dbh=&db_connect($db_host,$db,$db_user,$db_pass); while (1) { my $sqlquery="select id from interfaces order by rand() limit 0, 5"; my $obj=&db_query($dbh,$sqlquery); my $ntuples=$obj->rows(); my $debug=1; while (my $ref = $obj->fetchrow_hashref()) { my $interfaces_id=$ref->{'id'}; print "interfaces_id:$interfaces_id " if ($debug); &safefork; } print "-----------------------------------------------------------------------------------------------------------------\n"; } ############################################################## # This subroutine forks the recv() so the script doesnt hang!# ############################################################## sub safefork { my $pid_; my $return; my %SIG; $SIG{CHLD} = \&REAPER; # do something that forks... FORK: { if ($pid_ = fork) { # parent here # child process pid is available in $pid_ return ($pid_); } elsif (defined $pid_) { # $pid_ is zero here if defined # child here # Child code goes here! # parent process pid is available with getppid exit; } elsif ($! =~ /No more process/) { # EAGAIN, supposedly recoverable fork error #sleep 5; #redo FORK; # Just exit: exit; } else { # weird fork error print ("Can't fork: $!\n"); exit; } } } # end safefork sub-routine ######################################################################## # This subroutine is REAPER that prevents Zombies with his shiny scythe# # This is necessary on sysv due to the way it handles signals # ######################################################################## sub REAPER { my $child; my %Kid_Status; my %SIG; # If a second child dies while in the signal handler caused by the # first death, we won't get another signal. So must loop here else # we will leave the unreaped child as a zombie. And the next time # two children die we get another zombie. And so on. while (($child = waitpid(-1,WNOHANG)) > 0) { $Kid_Status{$child} = $?; } $SIG{CHLD} = \&REAPER; # still loathe sysV } # end REAPER sub-routine sub db_connect { my ($db_host,$db,$db_user,$db_pass) = @_; my ($dbh); my ($note_connect)=0; while (!$dbh) { $dbh = DBI->connect("DBI:mysql:$db:$db_host", "$db_user", "$db_pass", {PrintError => 0}); if (!$dbh) { $note_connect=1; sleep 2; } } if ($note_connect==1) { $note_connect=0; } return ($dbh); } sub db_query { my ($dbh,$sqlquery) = @_; my ($obj) = $dbh->prepare("$sqlquery"); if (!$obj) { exit; } if (!$obj->execute) { exit; } return ($obj); } # end db_query sub-routine;
The described behaviour is correct, because the forked child exits. Think of it as follows: Both the child and the parent contain an open database connection. The connection is attached to some Perl object. If the child exits, then Perl's garbage collector becomes active and destroys the child. Destroying the child means in our case, that the child closes the connection silently. Of course, the same connection and the socket remain open in the parent. However, from the servers point of view, the connection is closed anyways. If you are interested in further discussions, please do so on the mailing list perl@lists.mysql.com. Jochen
Darren, it may very well be, that my diagnosis is wrong. And that is exactly the reason why the discussion is better held on perl@lists.mysql.com: It's a place where Rudy Lippan, the current module maintainer will read your postings. Jochen