Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

There are a few postings about DBI handles and forking, but I seem to be having an odd problem (the best kind :) The general tone of using DBI and fork, is to create your dbi object after forking and then all is well... However I'm having some issues. First off, I'm using active perl but I hope that isn't the problem. Anyway, here is some code...
sub spider { my $pid=fork(); if ($pid) { print "Parent.. returning\n"; return; } use DBI; my $sdbh = DBI->connect( "DBI:mysql:dbase;", 'username','password' ) or die "Couldn't connect to database: " . DBI->errstr; print "spider post-fork\n"; my $string = "SELECT data FROM info WHERE name='spiders'"; my $sth = $sdbh->prepare($string); #$sth->{InactiveDestroy}=1; $sth->execute; my $data = $sth->fetchrow_arrayref(); my $p=$data->[0]; print "spider says P is $p\n"; for (my $i=1;$i<10;$i++) { print "forking for ftpspider\n"; $pid=fork(); if (!$pid) { print "child... calling ftpspider\n"; ftpspider($i); } print "parent... finishing loop\n"; $|++; } print "finishing up db connections\n"; $sth->finish; $sdbh->disconnect; } sub ftpspider { my $call=shift; $|++; print "ftpspider called with $call... we're the grandchild\n"; use DBI; print "DBI used ok\n"; my $gdbh = DBI->connect( "DBI:mysql:dbase;", 'username','password' ) or die "Couldn't connect to database: " . DBI->errstr; print "gdbh created ok\n"; $gdbh->do("UPDATE info SET data=data+1 WHERE name='spiders'"); print "updated ok\n"; print "done updating grandchild... disconnecting\n"; $gdbh->disconnect; print "grandchild done.... exiting\n"; exit; }
Although this code doesn't do much, it tends to hang at the second fork (forking for ftp spider) I'm not aware of any limitation of grandchild forking... My only guess right now is that the grandchild DBI in ftpspider is conflicting with the child DBI in spider somehow... (BTW, DBI is also needed in the parent). Anyone have any similar experiences with using multi-generational DBI's? FWIW, I've also tried moving one of the forks to the ftpspider function. I've also tried making a dbi handle in the spider function and passing it to the ftpspider after it forks. No luck either way. As far as error messages go, I've been getting the following:
dbih_clearcom (h 0x3659508, com 0x571e828): FLAGS 0x111: COMSET Warn PrintError TYPE 2 PARENT DBI::dr=HASH(0x3659538) KIDS 1 (1 Active) IMP_DATA HASH(0x3659448) in 'DBD::mysql::db' Attempt to free non-existent shared string during global destruction.
help :]

Replies are listed 'Best First'.
Re: DBI and fork()
by Juerd (Abbot) on Sep 27, 2002 at 22:32 UTC

    Attempt to free non-existent shared string during global destruction.

    One of the processes no longer uses the object, and wants to destroy it. Here's a piece of documentation on this:

    InactiveDestroy (boolean)

    This attribute can be used to disable the database engine related effect of DESTROYing a handle (which would normally close a pre- pared statement or disconnect from the database etc).

    For a database handle, this attribute does not disable an explicit call to the disconnect method, only the implicit call from DESTROY.

    The default value, false, means that a handle will be automatically destroyed when it passes out of scope. A true value disables auto- matic destruction. (Think of the name as meaning 'inactive the DESTROY method'.)

    This attribute is specifically designed for use in Unix applications that fork child processes. Either the parent or the child process, but not both, should set InactiveDestroy on all their shared handles. Note that some databases, including Oracle, don't support passing a database connection across a fork.

    - Yes, I reinvent wheels.
    - Spam: Visit eurotraQ.
    

      Juerd: I tried it (note the #$sth->{InactiveDestroy}=1; comment in there) I'm not sure I tried it on the dbh though. The reason I wasn't using it is because neither parent nor child share any database handles.
        He're is the output from the above program... its like the 2nd fork never happens...
        Parent.. returning spider post-fork spider says P is 0 forking for ftpspider