Appreciate insight on why if I have a defined SIG{__DIE__}, it is overriding a try/catch block?
It doesn't override it - you are, by calling exit inside the handler. You don't need to do that, since $SIG{__DIE__} gets called when the program is dieing anyway. If I remove the exit and leave the rest of the code unchanged, I get the output:
DIE ERROR: malformed JSON string, neither array, object, number, strin
+g or atom, at character offset 0 (before "(end of string)") at 120991
+8.pl line 26. :
Error decoding data from data1
Which is hopefully getting a bit closer to what you want. As for the special variables, I think you've got a couple of things mixed up:
$! doesn't have anything to do with the exit status of the program (and especially not when you set it with local). Setting $! with local won't work, as the changes will be local to the handler only.
- Try::Tiny gives you the error in $_, not $@.
- Checking $@ inside of the handler doesn't make sense to me - you aren't supposed to rely on the values of any of the Error Variables except for immediately after an operation that is documented to set them fails.
I really need the SIG_DIE functionality for the rest of the code, just not have it get int he way in the try/catch section
If you really don't want the handler to be called inside a try/catch, you can temporarily disable it like Athanasius suggested, although personally I would do it with local, that is: try { local $SIG{__DIE__} = 'DEFAULT'; ... (no other changes needed). It's also possible to use $^S, like Corion suggested, to customize the behavior of the handler based on whether it's inside an eval or not, for example by sticking die @_ if $^S; at the very beginning - although make sure to read all of the documentation, for example %SIG strongly cautions against using $^S!
Now, as for the custom exit code, it seems that unfortunately you can't set $? from within a $SIG{__DIE__} handler - although you can set it from inside an END block. Although I don't consider this the most elegant solution, something like this might be closer to what you want:
{ # block to hide $_exitcode from rest of program
my $_exitcode;
$SIG{__DIE__} = sub {
die @_ if $^S; # don't run this handler from inside "eval"
my $err = shift;
chomp($err);
print STDERR "DIE ERROR: $err\n";
$_exitcode = 2;
};
END { $?=$_exitcode if defined $_exitcode }
}
In any case, all of this seems like you're doing some relatively complicated error handling - I suggest you read all of the documentation I've linked above. Also, I would encourage considering if such complex error handling is necessary in the first place - if you could give some more background, like why you need all this (especially the custom exit code), and how you expect your program to behave exactly in the face of different errors, what kind of errors you are expecting, etc., perhaps we can suggest a better overall solution.
Update: As ikegami pointed out, $! is in fact related to the exit code, I was wrong above. And as it turns out, you can set it from inside the handler, which significantly simplifies the above code:
$SIG{__DIE__} = sub {
die @_ if $^S; # don't run this handler from inside "eval"
my $err = shift;
chomp($err);
print STDERR "DIE ERROR: $err\n";
$! = 2;
};
Although if, as you said in the reply, you want to temporarily disable the handler with local $SIG{__DIE__} = 'DEFAULT';, you can remove the die @_ if $^S; (I think that's probably better). If I use this handler in your original code (and I fix the $@/$_ mixup), I get the following output, without the "DIE ERROR:" message, which I think is what you wanted?
Error decoding data from data1 malformed JSON string, neither array, o
+bject, number, string or atom, at character offset 0 (before "(end of
+ string)") at 1209918.pl line 25.
|