in reply to Re^6: Net::SSH2 test connection to remote host
in thread Net::SSH2 test connection to remote host

In my opinion, DESTROY methods should not have side effects like changing $@ (or $? or $!), and if they do, it is a bug!

And I don't see that programming defensively against this kind of bugs is the right thing to do. It just complicates the code unnecessarily. The only reason I see to do that is when the DESTROY method is outside your control (i.e. in a package from CPAN).

But if it's your own code, just...

sub DESTROY { local $@; ... }

Replies are listed 'Best First'.
Re^8: Net::SSH2 test connection to remote host
by JavaFan (Canon) on Oct 01, 2008 at 09:44 UTC
    In my opinion, DESTROY methods should not have side effects like changing $@ (or $? or $!), and if they do, it is a bug!

    That's an opinion shared by others, but other people disagree. See for instance a thread about this on p5p this summer. Note that if DESTROY wouldn't propagate changes to $@, $! or $? DESTROY would be different from other functions, because $@, $! and $? behave differently. It also means you can have code that throws an exception, but afterwards $@ isn't set (your local $@ suffers from the same problem):

    sub one::DESTROY { die "foo\n"; } eval {my $x = bless [], 'one'}; say "\$\@ = $@"; __END__ $@ = (in cleanup) foo
    but
    sub one::DESTROY { local $@; die "foo\n"; } eval {my $x = bless [], 'one'}; say "\$\@ = $@"; __END__ $@ =
    This is far from ideal as well, and I doubt it's much better than the current situation.

    People have suggested a new variable, @@, where new errors get pushed onto, instead of having them override $@. But noone has written a patch to actually do this.

      ok, let me refine my comment:
      DESTROY methods should not have side effects like changing $@ unless they do it while dieing

      In other words, I have no problem if some DESTROY method dies and changes $@ while doing it.

      In practice, what I mean is that inside a DESTROY sub, if eval is used, $@ should be localized for its scope (and the same applies for $! and IO operations and $? and system, fork, etc.)

      For instance, I see no problem with this DESTROY method:

      sub DESTROY { my $self = shift; { local $@; eval { $self->whatever() }; } die "cleanup failed" unless $self->cleanup; }

      Regarding the p5p discussion, it was about whether this no-side-effects-from-DESTROY thing should be implemented at the interpreter level.