Subject: | DESTROY not called until application exits |
Date: | Tue, 13 Oct 2009 11:43:35 +0100 |
To: | bug-IMAP-Client [...] rt.cpan.org |
From: | Mike Cardwell <cpan [...] grepular.com> |
The DESTROY method has been implemented incorrectly to the extent that
it wont be called until the application ends.
When an object goes out of scope the DESTROY method is called on that
very object. By storing each object in a package variable on creation
you're guaranteeing that it doesn't go out of scope until the
application exits gracefully.
In the below example, when do_stuff returns I would expect the imap
connection to be disconnected automatically without me having to
explicitly call the disconnect() function, because the object has gone
out of scope:
======================================================================
foreach( @large_number_of_users ){
do_stuff( $_ );
}
sub do_stuff {
my $imap = new Lboro::IMAP::Client;
$imap->connect( PeerAddr => 'localhost', );
$imap->login( $_[0], 'pass', );
## Do some operations on the imap connection
}
======================================================================
It doesn't do that, because a copy of the object still exists in
$IMAP::Client::Instances so the DESTROY method isn't called. This can be
fixed by removing the Interfaces variable and simplifying DESTROY.
Here's a patch against 0.13:
======================================================================
--- Client.pm.original 2009-10-13 11:22:00.000000000 +0100
+++ Client.pm 2009-10-13 11:39:34.000000000 +0100
@@ -30,7 +30,6 @@
%EXPORT_TAGS = ();
# Create Class variables
-my %Instances;
my @SERVER_RESPONSES = ('exists', 'recent'); # constant value
my $server_response_callback = undef;
my $ID;
@@ -744,7 +743,6 @@
'auth' => '',
}, $proto;
- $Instances{$self->{'ID'}} = \$self;
# If a server was supplied, try to connect to it
if (my $server = shift) {
if ($self->connect(PeerAddr => $server)) {
@@ -760,18 +758,8 @@
}
sub DESTROY { # Undocumented: Not to be directly called
my $self = shift;
- if ($Instances{$self->{'ID'}}) {
- $self->disconnect(); # FIXME: Probably not nessesary
- delete $Instances{$self->{'ID'}};
- return;
- }
-
- # If we reach here, we didn't find ourself, which is a seirous
problem
- warn "ERROR: Could not find self in Instances upon DESTROY -
Something is seriously wrong!\n";
- foreach my $key (keys %Instances) {
- warn "PANIC DUMP: Instance name:
".(($Instances{$key}->{'name'}) ? $Instances{$key}->{'name'} :
"(none)")."\n";
- }
- die "DUMP COMPLETE: Aborting...\n\n";
+ $self->logout();
+ $self->disconnect();
}
##### Object manipulation functions
======================================================================