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

Eternal greetings, Perl Monks.

On a WindowsXP-Perl5.8 box, I have created the following error:

(in cleanup) Can't call method "close" on an undefined value at C:/Perl/site/lib/DBD/mysqlPP.pm line 314 during global destruction.

from the following code:

#!/usr/bin/perl -w use strict; use DBI; use CGI qw(fatalsToBrowser); my $q = new CGI; my $dbh = DBI->connect("dbi:mysqlPP:database=generator;host=localhost" +,"root", "mysql",{'RaiseError' => 1}); print $q->header, $q->start_html(); &display; print $q->end_html; $dbh->disconnect; exit; sub display { my $statement = qq(SELECT * FROM clients LIMIT 10); my $sth = $dbh->prepare($statement); $sth->execute(); my @row = $sth->fetchrow_array; $sth->finish(); print $q->p(@row); }

By my count there should be no errors in this. MysqlPP is at 0.04 and needs improvement but I don't think it should develop errors with this basic code.

I have written the author with no response. In Japan, the hour is late. I hope to blessed by your answer.

Replies are listed 'Best First'.
Re: mysqlPP.pm error
by hv (Prior) on Feb 18, 2003 at 23:33 UTC

    I think you're hitting a problem with order of destruction in final cleanup. You can probably preempt that by forcing the destruction earlier:

    $dbh->disconnect; $dbh = undef; exit;

    Hugo

      Wow! That did it.

      A funny thing is that it is not in any of the documentation. What is your guess as to the problem? Is it the module?

        When you have a complex data structure, the various parts of it normally get destroyed in a useful order because each object holds a reference to the things it contains: when you free up the top level object, its reference count goes to zero, which triggers its destruction, and that then releases all the things it refers to, reducing their reference counts, and allowing the destruction to cascade down from the top level object.

        When the program terminates, there is an additional process called "global destruction", and now it is a bit trickier: perl has no intrinsic information about which things are "top level" objects and which aren't, and so it goes around dropping reference counts on things in an effectively random order. That can mean that if you have a class like this:

        package MyClass; sub new { my $class = shift; bless { socket => $class->open_new_socket }, $class; } sub DESTROY { my $self = shift; $self->{socket}->close; }
        .. if the DESTROY is triggered during the global destruction phase it is quite possible that perl will already have freed $self->{socket} before freeing $self.

        I believe that DBD::mysqlPP has a DESTROY method very similar to the above to try and guarantee that its socket to the MySQL server is always cleanly closed down when the dbh goes away. There are various answers to "where is the problem", but I think I'd vote for the documentation (if this isn't mentioned there) or your reading of it (if it is). :)

        For more complex code, it can be helpful to keep the cleanup code close to the creation code, and you can do that by taking advantage of the fact that END handlers are run before global destruction:

        my $dbh = DBI->connect(...); END { $dbh = undef }

        Hugo