Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-28 Thread David Cantrell

Michael G Schwern wrote:


I realize this might be because rt.cpan.org
does not appear to have been sending out ticket emails.


The RSS feeds work though.  Shame there's no obvious way to sign up to 
one feed for all my modules, but I have a little shell script which 
periodically makes sure I'm signed up for all my individual feeds. 
Anyone who wants it, prod me off-list.


It assumes you use rss2email, but should be adaptable for all other 
sensible RSS tools.


--
David Cantrell


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-28 Thread A. Pagaltzis
* Joshua ben Jore [EMAIL PROTECTED] [2007-02-28 06:20]:
 On 2/27/07, A. Pagaltzis [EMAIL PROTECTED] wrote:
 Together with the contortions required to safely examine $@
 after an eval I'm getting tempted to put Unbreak::Eval on the
 CPAN.
 
 Please do.

I was joking, mostly; I have several other modules that I’m
already neglecting; it wouldn’t do anyone much good if I were to
add another neglected module to my directory. :-/

 Did David Golden ever send his $@ examining snippet to you? It
 did about the same thing so the multiple possible errors all
 got captured.

Nope.

I think it would already be a good idea if someone just collected
all the related issues and solutions in one prose document (maybe
as a meditation on PerlMonks) so whoever does have the time and
energy to tackle this can simply sit down and play from the
sheet.

Regards,
-- 
Aristotle Pagaltzis // http://plasmasturm.org/


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-28 Thread chromatic
On Wednesday 28 February 2007 12:53, A. Pagaltzis wrote:

 I think it would already be a good idea if someone just collected
 all the related issues and solutions in one prose document (maybe
 as a meditation on PerlMonks) so whoever does have the time and
 energy to tackle this can simply sit down and play from the
 sheet.

For what it's worth, I'm working on one for type checking in Perl (that 
is, Things you'd use ref() for if it actually worked).

-- c


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread Michael G Schwern
chromatic wrote:
 On Monday 26 February 2007 21:20, Michael G Schwern wrote:
 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!
 
 No, it's warning you that if Test::MockObject doesn't work, that it's not 
 *my* 
 problem.  It's also telling you exactly *where* that problem is.

If that were so it would only warn when a MockObject is looked at using
UNIVERSAL::isa/can() as a function.  That would cover the utility of warning
a user about a possible problem using mocked objects without launching a
UNIVERSAL::isa crusade.  As it is it warns on *any* use of UNIVERSAL::isa()
as a function, mocked object or no (although right now UNIVERSAL::isa
appears to not warn at all).


 As much as I'd like to fix the real problem (the belief that enforcing 
 structural subtyping makes any sense), the best I can do is try to work 
 around the damage while not sweeping it under the rug.
 
 I can't see how ignoring the problem gets it fixed.

While I understand the desire to want to fix other people's code and educate
users, there are many problems with this appraoch.  I've outlined them in
detail below but what it boils down to is this...

When I'm programming on a project I want to work on that project.  What I do
*not* want to do is have something totally unrelated nagging me to fix
potential bugs in someone else's code.  This would be like if you hired some
painters to paint your house and they keep bugging you every five minutes
that the potholes in the street need to be patched up, that my neighbor
really ought to sort his recycling better and my landlord really should have
the water heater inspected.  Its distracting and it does nothing to get my
actual work done.

Instead, a course of eduction and contacting the actual authors of the
naughty code is in order.  You've certainly started in on the former.  As
for the latter, I suggest doing a Google Perl code search for UNIVERSAL::
and contacting each of the authors.


Now for the analysis why putting crusader code into otherwise functional
modules is a bad idea:

_Modules are supposed to be modular_  They should avoid universal effects or
poking around in other namespaces without a damned good reason.  If I
download a module which does X I do not want it to also launch a Crusade
against other installed code.  Stay in your box.

_You're alerting the wrong person_  If there's a problem with a CPAN module
the author of that module should be told, not the users.  The users can't do
much but report the problem, which in the case of MockObject vs Class::DBI I
did.  And now I twiddle my thumbs waiting for a patch to be applied.
Meanwhile, my tests spew all sorts of warnings that don't indicate any
actual problem and I can't do anything more about.

_You're annoying the user_  By adding on Crusader Code to a module you're
causing annoyance to the users of your module who, as mentioned above, often
can't do much about it.

_You're annoying LOTS of users_  The solution to any particular mistaken use
of UNIVERSAL::isa in a CPAN module is for the author to patch it.  Maybe one
user reports the bug and provides a patch.  One user, one bug report, one
patch, one author.  In order to effect this change you are spewing warnings
at lots and lots of people, many of which can do nothing but report the bug.

_You're conflating two behaviors into one module_  I want to use
Test::MockObject to mock objects.  Scanning my code for mistaken uses of
UNIVERSAL::isa is another thing entirely that I may or may not want to do.
By bolting the two together it becomes impossible to do one without the
other.  This lowers the utility of MockObject.

_You can break other people's code_  By mucking with other people's code you
potentially *break* that code.  By *silently* changing the way isa() works,
or in Eric's case deleting a $SIG{__DIE__} handler, any mistake you make can
now break lots of other totally unrelated code.  Silently, unexpectedly and
very difficult to debug because nobody would think that loading MockObject
would have anything to do with Class::DBI (I didn't).  As UNIVERSAL::isa and
can have had and currently do have bugs (I can't even get UNIVERSAL::isa to
warn) you take what should be the safe action of loading a module and turn
it into a potential bomb for the whole system.



Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread chromatic
On Tuesday 27 February 2007 00:13, Michael G Schwern wrote:

 If that were so it would only warn when a MockObject is looked at using
 UNIVERSAL::isa/can() as a function. 

You really ought to read the code, especially the part where Test::MockObject 
and UNIVERSAL::isa and UNIVERSAL::can are separate modules.

The previous paragraph is brought to you by the word decoupled and the 
letters Q and A.

 That would cover the utility of 
 warning a user about a possible problem using mocked objects without
 launching a UNIVERSAL::isa crusade.  As it is it warns on *any* use of
 UNIVERSAL::isa() as a function, mocked object or no (although right now
 UNIVERSAL::isa appears to not warn at all).

Yes, that's what UNIVERSAL::isa and UNIVERSAL::can do.  They attempt to work 
around the damage of using base methods as functions and warn about them.

Test::MockObject and Test::MockObject::Extends use both other modules because 
that anti-pattern tends to break mock objects.

It tends to break other types of code too, which is why they are separate 
modules.

The previous three paragraphs are brought to you by the words modularity 
and generalization and the letters O, O, and P.

 When I'm programming on a project I want to work on that project.  What I
 do *not* want to do is have something totally unrelated nagging me to fix
 potential bugs in someone else's code.

When I'm programming on a project, I want the rest of the code to work and not 
generate strange failures.

 Instead, a course of eduction and contacting the actual authors of the
 naughty code is in order.  You've certainly started in on the former.  As
 for the latter, I suggest doing a Google Perl code search for UNIVERSAL::
 and contacting each of the authors.

That didn't work.

Chris Dolan, I believe, had an interesting conversation with Andy Wardley over 
strange Template Toolkit failures with Test::MockObject.  I believe this was 
also pre-UNIVERSAL::isa.

Even Ben Tilly, dispenser of voluminous wisdom on Perl Monks, still seems to 
believe that can() is a method not worth supporting because some people 
might not use it correctly.

 Now for the analysis why putting crusader code into otherwise functional
 modules is a bad idea:

 _Modules are supposed to be modular_  They should avoid universal effects
 or poking around in other namespaces without a damned good reason.  If I
 download a module which does X I do not want it to also launch a Crusade
 against other installed code.  Stay in your box.

UNIVERSAL::isa and UNIVERSAL::can are separate modules.  They don't know the 
internals of Test::MockObject nor any other code that might want to use them.  
This is on purpose.

 _You're alerting the wrong person_  If there's a problem with a CPAN module
 the author of that module should be told, not the users.

The users are the ones who will encounter the bugs when, as just one example, 
Test::MockObject falls prey to someone else's buggy code.

 _You're annoying the user_  By adding on Crusader Code to a module you're
 causing annoyance to the users of your module who, as mentioned above,
 often can't do much about it.

They can report the bug, much as they would have to do if they encountered it 
in practice.  However:

1) UNIVERSAL::isa and UNIVERSAL::can work around the bug
2) The warnings are merely warnings, not crashings and errors, as the bug 
would be
3) The warnings do their best to identify exactly *where* the bug is, which 
beats trying to figure out weird crashes all to pieces

 _You're annoying LOTS of users_  The solution to any particular mistaken
 use of UNIVERSAL::isa in a CPAN module is for the author to patch it. 
 Maybe one user reports the bug and provides a patch.  One user, one bug
 report, one patch, one author.  In order to effect this change you are
 spewing warnings at lots and lots of people, many of which can do nothing
 but report the bug.

Yet these bugs aren't getting fixed.

It seems to me that there's a different problem somewhere else.

Exactly how long have we been talking about UNIVERSAL::isa and UNIVERSAL::can 
*not* being functions?  Years!

Years!!

If I thought evangelism alone would work, I'd stick to that.

If I thought piling workaround upon workaround would work, I'd do that too, 
but I'm not a PHP programmer with a security hole.

 _You're conflating two behaviors into one module_ 

Again, you really ought to read the code.

 I want to use 
 Test::MockObject to mock objects.  Scanning my code for mistaken uses of
 UNIVERSAL::isa is another thing entirely that I may or may not want to do.
 By bolting the two together it becomes impossible to do one without the
 other.  This lowers the utility of MockObject.

Yeah, it really SUCKS that Test::MockObject has a chance of working despite 
bugs in other people's software.  The refund line is --- over there, right 
under the You're WELCOME! sign.

 _You can break other people's code_  By mucking with other people's code
 you potentially *break* that code.  By 

Re: using $SIG{__DIE__} correctly (if you must)

2007-02-27 Thread Eric Wilhelm
# from Michael G Schwern
# on Monday 26 February 2007 09:20 pm:

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.  

There's nothing vigilante about writing code that assumes other code 
will behave properly.  If I were going to put something on CPAN that 
messed with __DIE__ hooks, it would only be an audit module.  I'm 
certainly not going to put delete($SIG{__DIE__}) at the beginning of 
every module either (take a joke -- it saves typing.)  I will, however, 
refuse to say local $SIG{__DIE__} inside of every eval just because 
*maybe* *somebody* did *something* wrong *somewhere*.  The user has 
every right to shoot themselves in the foot however they see fit.

 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.

You're placing the blame in the wrong place.  Modules which rely on a 
poorly-implemented $SIG{__DIE__} are going to break anyway.  I'm just 
saying we should all leave the slack in the rope and not walk on 
eggshells.  If the poor sap (though I tend to give Perl programmers 
more credit than that) wants to send me an e-mail questioning why I 
would be so bold as to use eval, I'll happily diagnose the problem and 
send them in the right direction.

--Eric
-- 
Insert random misquote here
---
http://scratchcomputing.com
---


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread chromatic
On Tuesday 27 February 2007 13:42, Michael G Schwern wrote:

 This handily solves your stated purpose of warning the user about
 MockObjects not being used because of UNIVERSAL::isa mistakes WITHOUT
 warning the user about EVERY mistaken use of UNIVERSAL::isa.

$ perldoc perllexwarn

-- c


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-27 Thread Michael G Schwern
Eric Wilhelm wrote:
 There's nothing vigilante about writing code that assumes other code 
 will behave properly.  If I were going to put something on CPAN that 
 messed with __DIE__ hooks, it would only be an audit module.

Oh good.


 I will, however, 
 refuse to say local $SIG{__DIE__} inside of every eval just because 
 *maybe* *somebody* did *something* wrong *somewhere*.  The user has 
 every right to shoot themselves in the foot however they see fit.

Unfortunately your foot is on top of theirs because its 50/50 as to who the
user is going to email with the bug.  That said, I only bother with this
level of bulletproofing in things like Test::Builder and you're glad I do.


 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.
 
 You're placing the blame in the wrong place.  Modules which rely on a 
 poorly-implemented $SIG{__DIE__} are going to break anyway.  I'm just 
 saying we should all leave the slack in the rope and not walk on 
 eggshells.  If the poor sap (though I tend to give Perl programmers 
 more credit than that) wants to send me an e-mail questioning why I 
 would be so bold as to use eval, I'll happily diagnose the problem and 
 send them in the right direction.

That's very generous of you.


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread Michael G Schwern
chromatic wrote:
 On Tuesday 27 February 2007 13:42, Michael G Schwern wrote:
 
 This handily solves your stated purpose of warning the user about
 MockObjects not being used because of UNIVERSAL::isa mistakes WITHOUT
 warning the user about EVERY mistaken use of UNIVERSAL::isa.
 
 $ perldoc perllexwarn

Yes I'm aware of that.  It is lexical thus I cannot say this to switch off
the warning for good:

no warnings UNIVERSAL::isa;
use Test::MockObject;
...

I have to patch the code which is calling UNIVERSAL::isa() as a function.
Every instance of it in all the code I might use.  In the case of a CPAN
module it is not my code.  I might not even have write access to edit it.
Thus it provides no better option for the 3rd party user.

It is also the wrong solution when, in most cases, it actually is a mistake
to call UNIVERSAL::isa as a function.  It would be better to patch the code
(if I can and if I have the inclination) then to paper over it.

What is wrong with the proof-of-concept I proposed?


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread chromatic
On Tuesday 27 February 2007 13:58, Michael G Schwern wrote:

 What is wrong with the proof-of-concept I proposed?

The lines:

my $real_isa = \UNIVERSAL::isa;

...

if( ref $obj and eval { $obj-$real_isa(Test::MockObject) } ) {

-- c


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread Fergal Daly

On 27/02/07, chromatic [EMAIL PROTECTED] wrote:

On Tuesday 27 February 2007 13:58, Michael G Schwern wrote:

 What is wrong with the proof-of-concept I proposed?

The lines:

my $real_isa = \UNIVERSAL::isa;

...

if( ref $obj and eval { $obj-$real_isa(Test::MockObject) } ) {


Why not have something like

---
package UNIVERSAL::isa;
our %care_about;

sub import {
 my $self = shift;
 @[EMAIL PROTECTED] = ();
}

sub isa {
 my ($obj, $class) = @_;
 # do correct isa stuff
 warn my warning if (exists $care_about{$class}) or (exists
$care_about{ref $obj});
}

*UNIVERSAL::isa = sub \isa;
---
then in Test::MockObject;

use UNIVERSAL::isa __PACKAGE__;

you could even add caller() by default making no different at all.
Then you only give a warning when people call UNIVERSAL::isa on your
objects,

F


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread chromatic
On Tuesday 27 February 2007 14:25, Fergal Daly wrote:

 Why not have something like

 ---
 package UNIVERSAL::isa;
 our %care_about;

 sub import {
   my $self = shift;
   @[EMAIL PROTECTED] = ();
 }

 sub isa {
   my ($obj, $class) = @_;
   # do correct isa stuff
   warn my warning if (exists $care_about{$class}) or (exists
 $care_about{ref $obj});
 }

 *UNIVERSAL::isa = sub \isa;
 ---
 then in Test::MockObject;

 use UNIVERSAL::isa __PACKAGE__;

 you could even add caller() by default making no different at all.
 Then you only give a warning when people call UNIVERSAL::isa on your
 objects,

Yeah, I was thinking about that last night and this morning.  It's a little 
tricky to allow class methods too, but that part works in UNIVERSAL::isa and 
UNIVERSAL::can right now, so it's doable.

-- c


Re: Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-27 Thread Michael G Schwern
Fergal Daly wrote:
 sub isa {
  my ($obj, $class) = @_;
  # do correct isa stuff
  warn my warning if (exists $care_about{$class}) or (exists
 $care_about{ref $obj});

Consider what if $obj is a subclass of the class you care about?  That
should probably get checked, too, as it too overrides isa().  I believe its
going to have to be...

sub _do_i_care {
my $obj = shift;

for my $class (keys %care_about) {
return 1 if $obj-isa($class);
}

return 0;
}

I'm hand waving over the part where isa() might go into a deep recursion
back into UNIVERSAL::isa().

An alternative is to care about any object or class which overrides isa().

sub _do_i_care {
my $thing = shift;

my $isa = $thing-can(isa);
return 1 if $isa ne \UNIVERSAL::isa;
}

Again, hand waving over possible deep recursion into UNIVERSAL::can().


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-27 Thread A. Pagaltzis
* Michael G Schwern [EMAIL PROTECTED] [2007-02-27 06:25]:
 $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.

Owh goodness aragh *twitch*

Together with the contortions required to safely examine $@ after
an eval I’m getting tempted to put Unbreak::Eval on the CPAN.

-- 
*AUTOLOAD=*_;sub _{s/(.*)::(.*)/print$2,(,$\/, )[defined wantarray]/e;$1}
Just-another-Perl-hack;
#Aristotle


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-27 Thread Michael G Schwern
A. Pagaltzis wrote:
 * Michael G Schwern [EMAIL PROTECTED] [2007-02-27 06:25]:
 $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.
 
 Owh goodness aragh *twitch*
 
 Together with the contortions required to safely examine $@ after
 an eval I’m getting tempted to put Unbreak::Eval on the CPAN.

I was poking around in CGI::Carp and found this:

# The mod_perl package Apache::Registry loads CGI programs by calling
# eval.  These evals don't count when looking at the stack backtrace.
sub _longmess {
my $message = Carp::longmess();
$message =~ s,eval[^\n]+(ModPerl|Apache)/(?:Registry|Dispatch)\w*\.pm.*,,s
if exists $ENV{MOD_PERL};
return $message;
}

sub ineval {
  (exists $ENV{MOD_PERL} ? 0 : $^S) || _longmess() =~ /eval [\{\']/m
}



Re: using $SIG{__DIE__} correctly (if you must)

2007-02-27 Thread Joshua ben Jore

On 2/27/07, A. Pagaltzis [EMAIL PROTECTED] wrote:

Owh goodness aragh *twitch*

Together with the contortions required to safely examine $@ after
an eval I'm getting tempted to put Unbreak::Eval on the CPAN.


Please do. Did David Golden ever send his $@ examining snippet to you?
It did about the same thing so the multiple possible errors all got
captured.

Josh


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-27 Thread Joshua ben Jore

On 2/27/07, Joshua ben Jore [EMAIL PROTECTED] wrote:

On 2/27/07, A. Pagaltzis [EMAIL PROTECTED] wrote:
 Owh goodness aragh *twitch*

 Together with the contortions required to safely examine $@ after
 an eval I'm getting tempted to put Unbreak::Eval on the CPAN.

Please do. Did David Golden ever send his $@ examining snippet to you?
It did about the same thing so the multiple possible errors all got
captured.


Damn. That was intended to be private. Good thing it wasn't anything damning.

Josh


Re: using $SIG{__DIE__} correctly (if you must) (was: Object Identification Cold War and the return of autobox.pm)

2007-02-26 Thread Eric Wilhelm
# from Michael G Schwern
# on Monday 26 February 2007 01:50 pm:

And then someone defined a $SIG{__DIE__} so now its C{ local
$SIG{__DIE__};  eval { $obj-isa($class) } }

No.  If that $SIG{__DIE__} doesn't check $^S, then it's just 
delete($SIG{__DIE__}) and you're back to eval {$obj-isa($class)} and 
balance is restored.

--Eric
-- 
So malloc calls a timeout and starts rummaging around the free chain,
sorting things out, and merging adjacent small free blocks into larger
blocks. This takes 3 1/2 days.
--Joel Spolsky
---
http://scratchcomputing.com
---


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-26 Thread Michael G Schwern
Eric Wilhelm wrote:
 # from Michael G Schwern
 # on Monday 26 February 2007 01:50 pm:
 
 And then someone defined a $SIG{__DIE__} so now its C{ local
 $SIG{__DIE__};  eval { $obj-isa($class) } }
 
 No.  If that $SIG{__DIE__} doesn't check $^S, then it's just 
 delete($SIG{__DIE__}) and you're back to eval {$obj-isa($class)} and 
 balance is restored.

You don't want to delete someone else's $SIG{__DIE__}.  And how can you know
if it checks $^S (most don't)?  Or was that a round-about way to say you
should always check $^S in your $SIG{__DIE__} which would be great but
nobody does which brings me right back to it shouldn't be so hard to do it
right!


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-26 Thread Eric Wilhelm
# from Michael G Schwern
# on Monday 26 February 2007 03:29 pm:

Eric Wilhelm wrote:
 # from Michael G Schwern

 # on Monday 26 February 2007 01:50 pm:
 And then someone defined a $SIG{__DIE__} so now its C{ local
 $SIG{__DIE__};  eval { $obj-isa($class) } }

 No.  If that $SIG{__DIE__} doesn't check $^S, then it's just
 delete($SIG{__DIE__}) and you're back to eval {$obj-isa($class)}
 and balance is restored.

You don't want to delete someone else's $SIG{__DIE__}.

No, I do.  Why would anyone else's $SIG{__DIE__} be in my code?  Now, 
maybe you're going to say that someone might use my module and be upset 
because their broken $SIG{__DIE__} is broken.

And how can 
 you know if it checks $^S (most don't)?

Maybe some juggling of exit and die.  Hmm, sounds like a job for 
chromatic.  Acme::OhNoYouDidn::t?  Or, you could just curry it into a 
sub that does check $^S if you wanted to be safe and weren't concerned 
about the call stack.  Or you could always just walk down the hall and 
tell whoever wrote it to fix it.

 Or was that a round-about 
 way to say you should always check $^S in your $SIG{__DIE__}

Yeah.  No, I don't actually delete it.  But if you're having problems, 
delete() may well be the answer.

 which 
 would be great but nobody does which brings me right back to it
 shouldn't be so hard to do it right!

Why doesn't anybody do it right?  Yes, the docs say that it was an 
accident that $SIG{__DIE__} gets called from within an eval and that 
may be fixed in the future.  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.

--Eric
-- 
Anyone who has the power to make you believe absurdities has the power
to make you commit injustices.
--Voltaire
---
http://scratchcomputing.com
---


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-26 Thread Eric Wilhelm
# from Michael G Schwern
# on Monday 26 February 2007 05:53 pm:

Put another way... be lax in what you accept, strict in what you
output. 

That's a different subject having more to do with piped text than code 
(if anybody in this case is being strict about acceptance here, it's 
perl) and even if it weren't, that philosophy can only go so far.

What we have here is more a case of walking on eggshells, doing various 
preventative things in case somebody 'd.  How many cases can you 
account for?  And, is it worth the loss of an idiom to try to sweep 
this flaw under the rug?

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)}

Or you could always just walk down the hall and 
 tell whoever wrote it to fix it.
That's a long bloody hall you've got there for CPAN code.

I would hope to not find many modules on CPAN that install such a thing.  
It's global, so whoever wrote $0 gets to decide what to do with it. 
That's a pretty short hall in most sane situations.

And how do 
you know the user didn't intend it to run even if its in an eval?

The bit about it might be fixed later implies that this intention 
would eventually lead to disappointment anyway.

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!

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.

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.

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.

--Eric
-- 
The only thing that could save UNIX at this late date would be a new $30
shareware version that runs on an unexpanded Commodore 64.
--Don Lancaster (1991)
---
http://scratchcomputing.com
---


Re: using $SIG{__DIE__} correctly (if you must)

2007-02-26 Thread Michael G Schwern
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.


Why UNIVERSAL::(can|isa) Warn (was Re: using $SIG{__DIE__} correctly (if you must))

2007-02-26 Thread chromatic
On Monday 26 February 2007 21:20, Michael G Schwern wrote:

 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!

No, it's warning you that if Test::MockObject doesn't work, that it's not *my* 
problem.  It's also telling you exactly *where* that problem is.

As much as I'd like to fix the real problem (the belief that enforcing 
structural subtyping makes any sense), the best I can do is try to work 
around the damage while not sweeping it under the rug.

I can't see how ignoring the problem gets it fixed.

-- c