[CDBI] Class::DBI and forking

Carlos Vicente <cvicente-zZ82ZiX1S8l+u43qRgrggVnYRNhDb3e+9nwVQlTi/[email protected]>
Newsgroups gmane.comp.lang.perl.modules.class-dbi
Message-ID <[email protected]>
Hi Perrin and others,

I've come across an already discussed problem regarding forking in CDBI
and its problems with shared db handles.  I found the following thread:

http://lists.digitalcraftsmen.net/pipermail/classdbi/2006-March/000995.html

which refers to the use of the InactiveDestroy flag, overriding db_Main,
etc...

The problem is that the link in that particular thread is broken and I
cannot tell which changes exactly need to happen in the db_Main
subclass, Ima::DBI, etc...

I tried to make it work with the information I had.  I modified the code
to have the child process set InactiveDestroy and call db_Main to open a
new db connection.  However, it still throws db errors such as:

DBD::mysql::st fetchrow_array failed: fetch() without execute() [for
Statement "..."

So, obviously I'm still missing something.

Can anyone give me some more hints?
Any help would be much appreciated.

cv



Here's a snippet of the method that calls fork():

-------------------------------------------------

sub arp_update_all {
    my ($class, %args) = @_;
    $class->isa_class_method('arp_update_all');

    $openkids = 0;  
    my $wait  = 2;  
    my %caches;

    my $dbh = $class->db_Main;

    my $start = time;

    my $device_count;
    my $alldevs = Device->retrieve_all();
    while ( my $dev = $alldevs->next ){
	my $cache;
	my $pid;
	
      FORK: {
	  if ( $pid = fork ){
	      # parent here
	      $SIG{CHLD} = \&_reaper;
	  }elsif ( defined $pid ) { # $pid is zero here if defined
	      # child here
	      if ( !($dbh->{InactiveDestroy} = 1) ) {
		  $class->throw_fatal("Cannot set InactiveDestroy: ", $dbh->errstr);
	      }
	      $dbh = undef;
	      $dbh = $class->db_Main;

	      $cache = $dev->_get_snmp_arp();
	      $caches{$dev->id}{dev} = $dev;
	      $caches{$dev->id}{cache} = $cache;
	      exit;
	  }elsif ( $! =~ /No more process/ ) {
	      # EAGAIN, supposedly recoverable fork error
	      $logger->warn("Problem while forking: $!.  Waiting for $wait
seconds");
	      sleep($wait);
	      redo FORK;
	  }else {
	      # weird fork error
	      $class->throw_fatal("Cannot fork: $!") unless defined $pid;
	  }
      }


-------------------------------------------------

And my db_Main looks like:


    sub db_Main {
	my $self = shift;
	my $dbh;
	if ( $ENV{'MOD_PERL'} and !$Apache::ServerStarting ) {
	    $dbh = Apache->request()->pnotes('dbh');
	}else{
	    $dbh = $self->SUPER::db_Main();
	}
	if ( !$dbh ) {
	    $dbh = DBI->connect_cached($defaults{dsn}, $defaults{user}, 
				       $defaults{password}, $defaults{dbi_options});
	    
	    if ( $ENV{'MOD_PERL'} and !$Apache::ServerStarting ) {
		Apache->request()->pnotes( 'dbh', $dbh );
	    }
	}
	return $dbh;
    }

------------------------------------------------------
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.