R6D1H2 R6D1H2 - 3 months ago 19
Perl Question

Fork+DBI and statement handles

Situation



So I know that the connection gets shared across the processes and I can't use the connection I opened before the fork in the childprocesses.

I also know that perl complains when I try to do something like this:

my $sth = $dbConn->prepare($sql);
$sth->execute();
$dbConn->disconnect();
while(my @row = $sth->fetchrow_array){
print @row,"\n";
}


because I try to disconnect while the statement handle is still active.

Why does this work then:



my $sth = $dbConn->prepare($sql);
$sth->execute();
while(my @row = $sth->fetchrow_array){
my $pid = fork;
if(not defined $pid){
warn "Could not fork\n";
next; # abort loop
}
if($pid){
#Parent: Do nothing
}
else{
#do stuff
exit;
}
}


If the child closes it on exit shouldn't perl complain about a statement handle still being active? I also made sure that the execution of some processes is over before the loop is fully iterated and thought it might complain then but it didn't. Shouldn't I fetch array refs and iterate using them instead of my demonstrated approach in this scenario?

Answer

Update

You say in your comment above that the child processes do close the parent's database handle, so the only question is why there is no message about still-active statement handles associated with the closing of the handle

That is because the child process will also first close the statement handles on termination before closing the database handle, so there is no error condition to report



You don't say what database driver you're using, and it's my guess that you simply happen to have a well-behaving one

The documentation for the DBI module says this

For some drivers, when the child process exits the destruction of inherited handles cause the corresponding handles in the parent process to cease working.

so perhaps the driver you're using isn't one of those drivers

An alternative is that the code connecting to the database sets the AutoInactiveDestroy flag. It forces the DESTROY method to check whether the current PID is the same as one that created the database and statement handles, and is recommended practice for all new code anyway