Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Why isn't a fatal error trappable?

by perl-diddler (Hermit)
on Nov 16, 2010 at 11:27 UTC ( #871682=perlquestion: print w/ replies, xml ) Need Help??
perl-diddler has asked for the wisdom of the Perl Monks concerning the following question:

I have an error handler setup that seems to trap most errors, but one error it's not trapping, and I'm not sure why is "Modification of a read-only value attempted".

There's no indication that this error is untrappable in perldiag? Are there errors that are not trappable? If so, how would I know which don't get caught?

Usually I like to try to find out how I got there with a traceback and possible a dump of some key data structures...

Comment on Why isn't a fatal error trappable?
Re: Why isn't a fatal error trappable?
by choroba (Abbot) on Nov 16, 2010 at 11:43 UTC
    What do you mean by not trapping?
    $ perl -e 'eval {undef=1;1} or die "Died: $@"' Died: Modification of a read-only value attempted at -e line 1.
      I mean I have an error handler that normally traps errors, but it's not catching this one....

      (ie...using SIG{DIE} & SIG{WARN}...)

      For that matter, in this case, how do I test if a value is writable before writing to it?

      In this case the error is the result of attempting to assign to a variable that is declared as the result of being "aliased" to a 'stack' variable. I'm not sure how it would ever end up being 'readonly' -- undefined, MAYBE, but readonly??

      don't see how off hand...

        Should that be __DIE__ and __WARN__ ?

        -derby
        I can trap the error with a handler, too:
        $ perl -e '$SIG{__DIE__} = sub {die "Handled: @_"};undef=1' Handled: Modification of a read-only value attempted at -e line 1.
Re: Why isn't a fatal error trappable?
by BrowserUk (Pope) on Nov 16, 2010 at 11:46 UTC

    It is trappable:

    c:\test>perl -E"chop for 'fred'; print 'here' " Modification of a read-only value attempted at -e line 1. c:\test>perl -E"eval{ chop; } for 'fred'; print 'here' " here

    The only circumstance I'm aware of that it isn't, is if you supply a constant directly to a mutator:

    c:\test>perl -E"chop 'fred'; print 'here' " Can't modify constant item in chop at -e line 1, near "'fred';" Execution of -e aborted due to compilation errors. c:\test>perl -E"eval{ chop 'fred' }; print 'here' " Can't modify constant item in chop at -e line 1, near "'fred' }" Execution of -e aborted due to compilation errors.

    And that, I've always assumed, is because it is detected at compile time rather than runtime.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Interesting. Division by zero is intentionally deferred to compile time.

      $ perl -c -e'3/0' -e syntax OK $ perl -e'3/0' Illegal division by zero at -e line 1.

      Yet chop is constant folded even though that always results in an exception.

      Update: Ah! The exception is probably not from constant folding. It's probably a compile-time requirement for an lvalue.

      $ perl -e'chop "fred"' Can't modify constant item in chop at -e line 1, at EOF Execution of -e aborted due to compilation errors.

      runs afoul the same check as

      $ perl -e'"fred" = $_' Can't modify constant item in scalar assignment at -e line 1, at EOF Execution of -e aborted due to compilation errors.
Re: Why isn't a fatal error trappable?
by BrowserUk (Pope) on Nov 16, 2010 at 11:46 UTC

    It is trappable:

    c:\test>perl -E"chop for 'fred'; print 'here' " Modification of a read-only value attempted at -e line 1. c:\test>perl -E"eval{ chop; } for 'fred'; print 'here' " here

    The only circumstance I'm aware of that it isn't, is if you supply a constant directly to a mutator:

    c:\test>perl -E"chop 'fred'; print 'here' " Can't modify constant item in chop at -e line 1, near "'fred';" Execution of -e aborted due to compilation errors. c:\test>perl -E"eval{ chop 'fred' }; print 'here' " Can't modify constant item in chop at -e line 1, near "'fred' }" Execution of -e aborted due to compilation errors.

    And that, I've always assumed, is because it is detected at compile time rather than runtime.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      And that, I've always assumed, is because it is detected at compile time rather than runtime.
      So, eval your eval!
      $ perl -E 'eval {eval qq{chop "fred"}}; say "Hi"' Hi $

        Well yeah, but there's little point in deferring the inevitable. It's always going to fail, so why work so hard to make it happen at runtime?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Why isn't a fatal error trappable?
by derby (Abbot) on Nov 16, 2010 at 11:49 UTC

    What does your error handler look like? That error is trappable:

    #!/usr/bin/perl use strict; use warnings; eval { mod( 2 ) }; if( $@ ) { print "TRAPPED!\n"; print $@, "\n"; } sub mod { $_[0] = 1 }

    -derby
Re: Why isn't a fatal error trappable?
by fisher (Priest) on Nov 16, 2010 at 11:49 UTC
    Show us The Code, Luke.
      The whole program? I'm willing to paste it in, but I think people's eyes might pop.

      The error and contextual lines I'll put here, but if you want the full thing, I've no problems posting it...(terror though it may be!) The error happens on the 2nd run (cuz it only fetches 1 page at a time at this point). So showing the 1st and 2nd runs:

      Ishtar:/Torrents/home/law/info/images> crawl.pl Loop... No more pages 0 pages parsed in 4.21 seconds 0 items from cache, 1 new pages fetched, 1 new items fetched. 0 pages in Page queue, 0 items in requisite queue Ishtar:/Torrents/home/law/info/images> crawl.pl Loop... Start Dump: Modification of a read-only value attempted at /Torrents/home/law/bin/ +crawl.pl line 1729. Close with partial character at /Torrents/home/law/bin/crawl.pl line 7 +90.
      The code is in my "dumpfromstart" routine that's called during a program "fault" ... so the program is in the process of dying from an error already, ...OH FRACK...

      I just found it...BUT, I still am not sure why it's dying with a readonly-only error there.

      I was staring at the place where I got the 2nd error (+ the 'partial string' routine):

      #line 33 sub partial_string($$) { my ($string,$maxlen) = @_; my $len=$string?length $string:0; my $remainder=sprintf "..(%d more chars)...", $len - $maxlen; sprintf "%.*s%s",$maxlen,$string//"",$len>$maxlen ? $remainder:"" +; } #line 40 ... #line 1159 sub _get_Nth_framep { $_=$_[0]->{Parseable_PerTag_Space}; $_->[$_[1]]; } #line 1163 .... #line 1708 (tabs should display @ 2 spaces for best readability) sub dumpfromstart { #line 1709 if ($fault) { $SIG{__WARN__} = $SIG{__DIE__} = undef; confess "Double Fault\n"; } lock $fault; ++$fault; print "Start Dump:\n"; #line 1717 #truncate excessive output foreach my $pg ($page, $startpage) { last unless $pg; $pg->{content} = partial_string($pg->{content},32) if $pg && $startpage->{content}; $pg->{tagprint} = []; for (my $i=0; $i <= $#{$pg->{Parseable_PerTag_Space}}; ++$i) { alias my ($open_tag, $tag_output) = $pg->_get_Nth_framep($ +i); #line 1726 $tag_output = partial_string($tag_output,32) if $tag_o +utput; #line 1727 } } my $d; if ($page and $startpage != $page) { $d = Data::Dumper->new([ $startpage, $page ], [qw(startpage pa +ge)]); } else { $d = Data::Dumper->new([ $startpage, $PageQueue::PageQueue ], [ 'startpage', ]); } print $d->Dump; --$fault; }
      But the problem was before it ever got here in the actual error catch routine where I disabled the error handler before it ever called dumpfromstart:
      if ($Devel) { $SIG{__WARN__} = $SIG{__DIE__} = sub { $Carp::CarpLevel = 1 if defined $^S && !$^S; $SIG{__WARN__} = $SIG{__DIE__} = undef; &dumpfromstart if defined $^S; confess $_[0] if defined $^S; die "exiting\n"; } }
      Sigh....

      It still doesn't really tell me why it's dying from a read-only assignment there, since the place where it's dying should be "on the stack" -- OR possibly undefined -- but if it was undefined, it wouldn't /shouldn't the assignment "auto-vivify" the undef?

      I'm not sure how that statement would ever die from an assignment to a readonly var... Maybe "alias" creates a condition where auto-vivify doesn't happen? ...hmmmm

      P.S. -- you can see the start of the bit of the other problem I mentioned right after this one (chronologically).... I.e. utf8 routines are complaining about binary output not looking right...

        The whole program?

        No, a minimal runnable demonstration of the problem.

Re: Why isn't a fatal error trappable?
by SimonClinch (Chaplain) on Nov 16, 2010 at 15:42 UTC
    It isn't a runtime error - the interpreter has parsed the code and bombed out with out even executing the first line of your script. perl -d is a good test -- does the error get trapped by the interpreter before offering you the first executable line of your code for step execution?

    One world, one people

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://871682]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (13)
As of 2014-12-17 21:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (34 votes), past polls