http://www.perlmonks.org?node_id=295103

gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:

From all the doc I can find DBI::clone() should create a duplicate of the established connection by using the same information originally used to connect. I have a process that forks of child processes and I want each one to have their own connection to the DB.

The problem is that the clone() gives all the child processes the same handle. I was under the assumption that the code for the child process would not be executed until after the fork, if this is so then each child should get a unique connection. Can someone explain why each child proc has the same handle?

Here is what I get when I run the code below:

Parent db handle is DBI::db=HASH(0x7381e8) I'm child 6302 with db handle DBI::db=HASH(0x74fc2c) I'm child 6303 with db handle DBI::db=HASH(0x74fc2c) I'm child 6304 with db handle DBI::db=HASH(0x74fc2c) I'm child 6305 with db handle DBI::db=HASH(0x74fc2c) I'm child 6306 with db handle DBI::db=HASH(0x74fc2c) I'm child 6308 with db handle DBI::db=HASH(0x74fc2c) I'm child 6307 with db handle DBI::db=HASH(0x74fc2c) I'm child 6310 with db handle DBI::db=HASH(0x74fc2c) I'm child 6309 with db handle DBI::db=HASH(0x74fc2c)
snip...
for (my $counter = 1;$counter < $MAXCHILDREN;$counter++) { if (my $pid = fork) { # in parent, do nothing } elsif (! defined $pid) { print "fork failed! -->$!\n"; exit; } else { my $new_dbh = $dbh->clone(); print "I'm child $$\n\twith db handle $new_dbh\n"; exit; } }
...snip

Replies are listed 'Best First'.
Re: Using DBI::clone()
by herveus (Prior) on Sep 29, 2003 at 21:13 UTC
    Howdy!

    ...well, each child is doing exactly the same thing immediately after the fork, so each one of those HASH(0x74fc2c) thingies is at the same address in the address space of each process, but not the same physical address. At least that is how I see it...

    It suggests that memory allocation is very deterministic. :)

    yours,
    Michael

      Yup -- the fact that the DBI::dbh objects are allocated into the same Perl address in each child doesn't mean that their internal state, such as a DBMS's session or connection ID, would be identical.

      You might try checking your database server to confirm that it knows about each of the connected clients.

Re: Using DBI::clone()
by rob_au (Abbot) on Sep 30, 2003 at 04:49 UTC
    You might want to have a read of the DBI man page, specifically the section relating to Threads and Thread Safety as the behaviour which you are describing is similar to that performed when additional threads are created after the creation of a DBI object. Cloned DBI objects retain the internal data pointers of the original object - This in turn causes a threaded Perl to croak when accessing DBI handles which do not belong to the current thread (excepting DESTORY).

    Similarly, the outcome of all this is that if you want each forked process to have a separate database handle, these handles should be created after forking the original process.

     

    perl -le "print+unpack'N',pack'B32','00000000000000000000001010001000'"

      Thats actually what I thought but I still didn't understand why each handle in the child (after forking) was the same. One would think (expect?) that they would be different.

      I guess I'll just have to connect to the DB manually in the child post-fork.