Date: | Tue, 03 Feb 2004 12:11:35 +0100 |
From: | Sascha Herrmann <s.herrmann [...] nttcable.de> |
To: | bug-Mail-IMAPClient [...] rt.cpan.org |
Subject: | usage of $@ for errormessage kills exception handling |
Hy,
i just had some Problems with Mail::IMAPClient and Exception Handling.
Maybe it is more something to add to the manpage than an real Bug.
The Problem occurs when you create an object $o of an class A which
creates an instance of the Mail::IMAPClient class and define an DESTROY
method in A which calls $imap->disconnect (where $imap is the instance
of Mail::IMAPClient). When you now call an die somewhere in your code
which brings $o out of scope so that the Garbagecollection calls
A::DESTROY the call to $imap->disconnect destroys the content of $@ just
after you called die but just befor your exception handling code.
To fix this Problem one must call local $@ in the DESTROY method. Since
this problem is somewhat hard to find you maybe should add an note about
that to the man page.
Second the manpage says: According to the standard, a well-behaved
client should log out before
closing the socket connection. Therefore, Mail::IMAPClient will
attempt
to log out of the server during DESTROY processing if the object
being
destroyed is in the Connected state.
As i watched into the code IMAPClient just returns undef when DESTROY is
called, but doesn't call logout or disconnect.
Version of IMAPClient: 2.2.6
I have attached some example code showing the problem.
Best Regards,
Sascha Herrmann
#!/usr/bin/perl -w
use strict;
use Mail::IMAPClient;
sub useit {
my $a = A->new();
# will raise an exception
# GC will free $a and call A::DESTROY
$a->do_something();
print "will never print this\n";
}
eval {
useit();
};
if ($@) {
print "\$\@: ", $@;
} else {
print "\$@ undefined";
}
package A;
sub new {
my $self = bless {};
$self->{imap} = Mail::IMAPClient->new( Server => 'xxx',
User => 'xxx',
Password => 'xxx');
return $self;
}
sub do_something {
die "byebye";
}
sub DESTROY {
my $self = shift;
# using local will fix the problem
#local $@;
print "\$\@ before disconnect: $@\n";
# affter disconnect $@ will be set to '' !!!
$self->{imap}->disconnect();
print "\$\@ after disconnect: $@\n";
}