[CDBI] Class::DBI and forking

Carlos Vicente cvicente at network-services.uoregon.edu
Wed Jan 10 01:24:13 GMT 2007


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;
    }

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





More information about the ClassDBI mailing list