Subject: | Moose::Object DESTROY still needs to localise more |
Date: | Tue, 15 Sep 2009 21:17:20 +0100 |
To: | bug-Moose [...] rt.cpan.org |
From: | Zefram <zefram [...] fysh.org> |
Re bug #48271, I see that you're now explicitly localising $?, and
Try::Tiny localises $@. Those are fine. But object destruction can
still clobber $!, $^E, and $., and that's still a problem. Here's an
example of how clobbering $! can lose:
use warnings;
use strict;
{
package TestObj;
use Moose;
sub DEMOLISH {
open my $fh, "<", "/bar";
if($fh) {
# hypothetically might do some I/O here
}
}
}
do { my $t = TestObj->new; mkdir("/foo") }
or die "mkdir failed: $!\n";
Assuming you're not root, the mkdir will fail with EACCES (Permission
denied). The die attempts to put this status into an exception message.
Between the mkdir and the die, though, $t gets destroyed, and its attempt
at I/O fails with ENOENT (No such file or directory). It clobbers $!,
and the program ends up showing the wrong error message. This is a
reasonable coding pattern, and for it to work the destructor needs to
localise $! to avoid clobbering it. The localisation can either go in
every individual DEMOLISH method that has a chance of clobbering it, or go
in Moose::Object::DESTROY. I recommend that the framework should do it.
The use case for $^E is identical, because it's an auxiliary OS error
code and is set in the same situations as $!. It doesn't do anything on
Unix, though, so it's a little harder to demonstrate. Also more likely
to be forgotten if every DEMOLISH author is responsible for localising it.
$. gets changed by I/O. More specifically, the aspect of $. that
behaves as a local status indicator is not the value visible in it
(which is actually persistent state of some filehandle) but *which*
filehandle it points at. This gets changed whenever input is performed
with a different filehandle. It could be clobbered by a destructor
quite similar to the one in the example I gave above. The same issues
apply as with $!, $?, and the rest, but $. is even more likely to be
overlooked by individual destructor authors.
-zefram