views:

58

answers:

2

It's taken me a while to track down a sudden problem with my code, but it appears that WWW::Mechanize::GZip is somehow triggering my $SIG{DIE} handler. Consider this code:

use strict;
use WWW::Mechanize::GZip;

$SIG{__DIE__} = sub {
   print "WTF???  WHY IS THIS BEING TRIGGERED?\n";
};

my $mech = WWW::Mechanize::GZip->new();
$mech->get( 'http://ammoseek.com/' );

print $mech->content(), "\n";

Any idea why this would be happening? And what can I do to prevent it?

Thanks,

-Mike

+2  A: 

You can find out details of what/how died by having your $SIG{__DIE__} handler print:

  • Error message ($_[0] in the handler)

  • Stack trace (e.g. by calling Carp::cluck) from within the handler

As an alternative, use onerror => \&func parameter to WWW::Mechanize::GZip constructor to create custom error handler (assuming the error is not from Compress::Zlib). From WWW::Mechanize POD

onerror => \&func

Reference to a die-compatible function, such as Carp::croak, that is called when there's a fatal error.

If this is set to undef, no errors will ever be shown.

If this value is not passed, Mech uses Carp::croak if Carp is installed, or CORE::die if not.

Since WWW::Mechanize::GZip is a direct subclass of WWW::Mechanize, you can use the same parameters to constructor in it.

DVK
Setting onerror to undef doesn't work, unfortunately. I emailed Peter Giessner, the module's author, and he suggested I simply create a local $SIG{__DIE__} to ignore all gunzip errors...
Mike
Probably comes from Compress::Zlib
DVK
@Mike: that will also ignore every other error, unless you customize your DIE handler a bit.
Ether
A: 

Assuming there isn't a real exception, that is, that the code runs normally without the $SIG{__DIE__}, then something, somewhere inside that method call is probably using eval BLOCK to trap and recover from an error. One of several problems with using eval BLOCK as an exception handler is that it triggers $SIG{__DIE__} even though it really shouldn't.

To avoid this, check that $^S is false in your $SIG{__DIE__}.

local $SIG{__DIE__} = sub {
    return if $^S;

    ...your error catching code...
};

See perlvar for more details.

BTW You can discover the details of the exception which is triggering this by printing @_.

local $SIG{__DIE__} = sub {
    print "SIGDIE caught @_";
};

Better yet, unless you really need a global die handler, use eval BLOCK.

eval {
    my $mech = WWW::Mechanize::GZip->new();
    $mech->get( 'http://ammoseek.com/' );
    1;
} or do {
    die "WWW::Mechanize::GZip failed and said: $@";
};

And have a look at Try::Tiny for a better exception handler.

Schwern