Eric Wilhelm wrote:
>> Also this:
>>  eval { delete $SIG{__DIE__};  $obj->isa($class) }
>> is no shorter than this:
>>  eval { local $SIG{__DIE__};  $obj->isa($class) }
> 
> To be clear (since I must not be funny enough), the delete() bit was a 
> joke.  This is much shorter than both:
> 
>   eval {$obj->isa($class)}

You seem to be saying "everyone should fix their shit" which I would love to
see happen.  Meanwhile, you've got to deal with broken or impolite shit.
Fortunately, since most folks localize their __DIE__ handlers, this usually
isn't a concern except to authors of really widely used modules.


>>> But, it's very clear in both perlvar and
>>> perlfunc#die, so why bother with the eval {local $SIG{__DIE__}; ...}
>>> mess?  Just cause broken code to break instead of working around it.
>> BECAUSE WE ALL THROUGHLY STUDY THE DOCUMENTATION, RIGHT?!
>>
>> Yeah.
> 
> Thoroughly study?  It apologizes about the brokenness (in both places) 
> before it even explains how to use it!

I still hold that even if folks have read the docs on this subject, and not
everyone learns $SIG{__DIE__} by studying perlvar, they don't remember it.
I usually forget about it.  Its simply not a day-to-day concern and there's
just too many damned exceptions to keep in mind.

And then there's still my assertion that until 5.8, $^S is not reliable.  So
even if you wanted to do it right it doesn't work!

$SIG{__DIE__} = sub {
    # We don't want to muck with death in an eval, but $^S isn't
    # totally reliable.  5.005_03 and 5.6.1 both do the wrong thing
    # with it.  Instead, we use caller.  This also means it runs under
    # 5.004!
    my $in_eval = 0;
    for( my $stack = 1;  my $sub = (CORE::caller($stack))[3];  $stack++ ) {
        $in_eval = 1 if $sub =~ /^\(eval\)/;
    }
    ...
};

That's how you do it "right" and maintain any sort of backwards compatibility.


>> People do it wrong because its easier to do it that way.  And it
>> usually works fine.  Most people don't even know about $^S.  Hell,
>> even the designers didn't think of it as evidenced by the accidental
>> feature.
>>
>> Doing it slightly wrong but usable is easier than doing it right.
>> That's why nobody does it right.  Design failure.
> 
> Sure it's a design failure.  But, breaking broken code is easier than 
> accounting for ignorance with the unfortunate side-effect that the user 
> learns something.  The ignorance goes away and balance is restored.

Again, you're assuming the "user" here to be the author of the naughty code
in question.  Or that you can write code which knows what's naughty and
what's intended.  I say that most of the time such vigilante coding will
only bother 3rd parties who use your vigilante module in conjunction with
someone else's code.  Your CPAN module is going to break other CPAN modules
and the poor sap using them who didn't write any of it is going to have no
idea why.

Case in point... my tests started suddenly warning about "UNIVERSAL::isa
called as a function in Class::DBI".  After spending a bunch of time trying
to figure out what the hell was going on and if Redhat introduced some new
warning or something I finally discover that Test::MockObject uses
UNIVERSAL::isa() which warns if *anyone* calls UNIVERSAL::isa() as a
function.  Its nagging *me*, the unrelated 3rd party, about problems in
someone else's code that I don't have control over!

Finally, if I download a module to do X I expect it to do X and not try to
Cure The Ills of the World.  Just as Test::MockObject should be about mock
objects and not about Spreading The Word about UNIVERSAL::isa(), your module
should not be about smiting others for using $SIG{__DIE__} improperly.

If you want to Cure The Ills Of The World contact the authors directly and
provide a patch.


> To be clear, I totally agree that it is a design failure.  To cite a 
> seemingly completely unrelated issue:  a buggy reimplementation of 
> require() that is a direct result of not understanding that a bad 
> $SIG{__DIE__} could be fixed to allow eval {require foo} (and possibly 
> not realizing that local $SIG{__DIE__} would be an option.)  So, the 
> code in question digs around in @INC to see if it can find a file.  
> Unfortunately, that solution breaks @INC subrefs.  So, now we're down 
> an idiom and a feature!  If the perpetrator of the die hook in question 
> had just been told "too bad", that mess wouldn't have happened.

Having written such things, yes its very hard to get all the tiny little
nuances right.  I know I've got stuff that blows up with code refs in @INC.
 UNIVERSAL::require probably has all sorts of interesting edge cases.  Right
now I'm teasing apart the code in Test::More to deal with overloaded objects
which don't implement stringify.  It sucks.


> Yeah, it shouldn't suck that much and ruby should be faster and perl 6 
> should be out by now and python should just exit instead of suggesting 
> that maybe you meant Ctrl-D.

Whoa there, boy.  Ease down.

Reply via email to