in reply to Rethrowing with die $@ considered harmful

I don't know if its directly related, but this makes me think of a LDAP helper module I wrote for a system I now have in production.

I won't go into too much detail, but (among other things) it had a "login" and "logout" method. Each updated a global session data hash with info about the current user. These methods throw exceptions if something goes wrong. Nothing fancy so far.

Later, I wanted to make a facility for administrators to "become" a normal user (think Unix "su"). However, I wanted to make it so that if the operation failed, it would restore the existing session. So, I wrote this code:

my %ubackup = %udat; eval { $self->logout; $self->login(username => $username); }; if($@) { %udat = %ubackup; die $@; }
Now this looks fine, but any errors were being mysteriously swallowed. Turns out the culprit was my LDAP object destructor, which did this:

sub DESTROY { my ($self) = @_; eval { $self->_unbind; }; }
ie shut down the connection, and ignore errors.

The login/logout methods create LDAP objects as part of their operation, so of course they were being destroyed at the end of the method. The call to _unbind was trampling $@.

This was a nightmare to track down. The solution was to simply localise $@ in the destructor.

local $@; eval { $self->_unbind; };