in reply to Re: DESTROY and DBI
in thread DESTROY and DBI

No, krisahoch, he can return the database handle and modify %{$self} as a side effect...

Mark, is $self properly blessed into the package? Otherwise, DESTROY would never be called...

It could also be the global cleanup order problem mentioned in this thread.

Have you tried using this class only from a subroutine? Take the part of the code at the top level that uses this class, and wrap it in a sub. Then put

$|=1; # make sure we see printouts and warns in order print "Before sub\n"; subThatUsesClass(); print "After sub, I _better_ have seen DESTROY happen...\n";
If it's the random global cleanups causing the problem, having your variable as a lexical in the sub should get it cleaned up properly...
--
Mike

Edit: Put in correct link to tilly's excellent description of the global cleanup problem...

Replies are listed 'Best First'.
Re: Re: Re: DESTROY and DBI
by mce (Curate) on Aug 27, 2002 at 13:26 UTC
    Hi Mike,
    Yes, of course I bless my object.
    I even tried this, but I think it is the same as during the exit.
    my $o=new MyClass; my $dbh=$o->opendb; warn $o->{_dbh}; warn $dbh; # the same as the previous line undef $o; exit;
    I cannot put it as a lexical in the sub because I have just written an entire framework (+5000 lines), consisting of a tree of packages in OO, and setting the DBI object as an attribute has an advantage of using persistant DB connections.

    This is the actual opendb routine

    sub opendb { my $self=shift; local($@); if ( not $self->{_dbh} or not $self->{_dbh}->ping) { eval{ $self->{_dbh}=$self->{_dbi}->connect() ; } ; if ( $@ ) { $self->Log('!',$@) and die "db gives error" ; } } $self->{_dbh}->{LongReadLen}=100000; # to handle Long column types $self->{_dbh}->{LongTruncOk}=0; # generates an error when the dat +a is too long $self->{_dbh}->{AutoCommit}=0; # Lets run transactional return $self->{_dbh}; }
    And I call this opendb as much as I like, without going to the db everytime. (note $self->{_dbi} is a object from my superclass of DBI). And the link to tilly's one, that was the one I was referring to, but using flyweightwrapper is a bit overshooting, I think.
    ---------------------------
    Dr. Mark Ceulemans
    Senior Consultant
    IT Masters, Belgium
      (Edit: I don't believe _dbh goes away before $self does, I think DBI is unloaded before the global cleanup happens; that's why I'm suggesting this END{} fix...)

      Hmmm, you don't need the total encapsulation features of the FlyweightWrapper, either...

      I'm betting packages get unloaded correctly. What happens if you add a hash at the package level in your class called instances, and do this:

      # private hash of instances my %instances; #... sub new { # ... build up $self, bless it, do whatever $instances{$self}=1; # ... whatever else you need to do... } #... sub DESTROY { # don't double-destroy return unless $instances{$self}; #... do whatever $instances{$self}=0; } END { foreach my $instance(keys %instances) { $instance->DESTROY() if $instances{$instance}; } }
      Offhand, I can't remember whether calling DESTROY directly is ok or not, but if not, you could get the same effect with a helper sub that DESTROY calls.
      --
      Mike

      Edit: I forgot to check $instances{$self} at the top of DESTROY