Skip Menu |

This queue is for tickets about the Mail-IMAPClient CPAN distribution.

Report information
The Basics
Id: 5181
Status: resolved
Priority: 0/
Queue: Mail-IMAPClient

People
Owner: Nobody in particular
Requestors: s.herrmann [...] nttcable.de
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



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"; }
New maintainer. yes, it was an unlucky choice of the authors to used $@ for the errors... Anyway, too late to change. Object destruction is nearly impossible to right in Perl, certainly when threads are used. Although good clients should cleanly disconnect, I think it is not too bad to behave as a bad client... just disconnecting. One workaround would be to sub DESTROY() { local $@; $self->disconnect; } But that only solves your problem... there are more.