I'm aware of the fact that $# is a global variable, still I can't figure out why I need to localize it before using eval:
For instance:
eval { SOME_FUNC_THAT_MAY_DIE(); };
if ($#) {
print "An error occured!\n";
}
The only possible thing I can think of is, if some signal handler will call die at the same time I try to read $#, what am I missing here?
The reason to say local $# before calling eval is to avoid stepping on your caller's $#. It's rude for a subroutine to alter any global variables (unless that's one of the stated purposes of the subroutine). This isn't really an issue with top-level code (not inside any subroutine).
Also, on older Perl's, any eval called during object destruction would clobber the global $# (if the object was being destroyed because an exception was being thrown from an eval block) unless $# was localized first. This was fixed in 5.14.0, but many people are still running older Perls.
The Try::Tiny module documentation gives the rationale (as well as providing an alternative):
When you run an eval block and it succeeds, $# will be cleared, potentially clobbering an error that is currently being caught.
This causes action at a distance, clearing previous errors your caller may have not yet handled.
$# must be properly localized before invoking eval in order to avoid this issue.
More specifically, $# is clobbered at the beginning of the eval, which also makes it impossible to capture the previous error before you die (for instance when making exception objects with error stacks).
You don't need to, but if you wrote code like this, localizing $# would keep the first error as it was. and if you didn't write code like this, the local $# would have no effect. better would be to handle errors before running any extra code.
eval {
die "error 1\n";
};
foo();
print "processing $#\n";
sub foo {
#local $#;
eval {
die "error 2\n";
};
}
Related
I had seen some exceptions that pointed to (end of) the catch block itself (see the example below).
As my opinion, this is an unexpected behavior, since it alters the location of original exception and make difficult to debug (it should say die at line 13.)
It shows the (correct) line 13, if I use die/confess or using eval instead try-catch.
Not knowing how my code will be called within the stack, I started to avoid using croak now. What do you think? Did I get right, or there is a way to improve this?
Best regards, Steve
use Carp;
use Try::Tiny;
try {
foo();
}
catch {
# do something before die
die $_;
}; # this is line 10
sub foo {
croak 'die'; # this is line 13
}
Output:
die at line 10.
This is the intended behavior from Carp
[...] use carp() or croak() which report the error as being from where your module was called. [...] There is no guarantee that that is where the error was, but it is a good educated guess.
So the error is reported at where the module's sub is called, which is what the user wants
use warnings;
use strict;
use feature 'say';
use Try::Tiny;
package Throw {
use warnings;
use Carp qw(croak confess);
#sub bam { die "die in module" }; # l.11
sub bam { croak "croak in module" };
1;
};
try {
Throw::bam(); # l.17
}
catch {
say "caught one: $_";
die "die in catch: $_";
};
say "done";
Prints
caught one: croak in module at exceptions.pl line 17.
die in catch: croak in module at exceptions.pl line 17.
If the sub throws using die then this is reported at line 11, what is the normal behavior of die, and what you seem to expect.
If any of this is unclear or suboptimal then better use confess and nicely get a full stacktrace. Also, if you wish more exception-based-like code behavior, can put together an exception/error class and throw its object,† designed and populated as desired.
If you want to confess an object note that at this time Carp has limits with that
The Carp routines don't handle exception objects currently. If called with a first argument that is a reference, they simply call die() or warn(), as appropriate.
One way then would be to confess a stringification of the object,‡ getting at least both a full stack backtrace and whatever is in the object.
I get the same behavior with eval, by replacing try-catch and $_ above
eval {
Throw::bam();
};
if ($#) {
say "caught one: $#";
die "die in catch: $#";
};
Prints exactly the same as above
While the above is clear and behaves as expected, a weird thing is indeed seen in the question's example: the error is reported from the whole try-catch statement, ie. at its closing brace, where line 10 is. (The try sub is prototyped and the whole try-catch is a syntax aid equivalent to a call to try that takes an anonymous sub, and then perhaps more. See ikegami's comment, and docs. Also see this post for more about its syntax.)
This is strange since the call to the croaking sub is foo() inside the try statement and this line should be reported, what can be confirmed by running the script with -MCarp::Always. But in the code in this answer the line of the call to Throw::bam is indeed reported -- why this difference?
The clear purpose of croak is to be used in the libraries, so that the user can see at which point in their (user's) code they called the library in a way that triggered an error. (While die would point to the place where error is detected, so in the library, most likely useless to the user. But read die and Carp docs for related complexities.)
What isn't obvious is that when croak is emitted in the same namespace (main::foo()) from try-catch in its own namespace (Try::Tiny) things get confused, and the end of its statement is reported. This can be checked by adding a foo() to my code above and calling it (instead of a sub from a module), and we get the question's behavior reproduced.
This doesn't happen if main::foo() with croak inside is called from a (complex) statement right in main::, so it seems to be due to the try-catch mix up of namespaces. (On the other hand, try-catch sugar adds an anonymous sub to the callstack, and this sure can mix things up as well.)
In practical terms, I'd say: always use croak out of modules (otherwise use die), or, better yet if you want to mimic exception-based code, use confess and/or your exception class hierarchy.
† Even just like die ExceptionClass->new(...);
Bear in mind that in the way of exceptions Perl only has the lonesome die, and eval. For more structure you'll need to implement it all, or use frameworks like Exception::Class or Throwable
‡ By writing and using a method that generates a plain string with useful information from the object, for Carp::confess $obj->stringify.
Or by overloading the "" (quote) operator for the class since it gets used when confess-ing an object (string context), for Carp::confess $obj; this is good to have anyway.
A basic example for both:
use overload ( q("") => \&stringify );
sub stringify {
my $self = shift;
join ", ", map { "$_ => " . ( $self->{$_} // 'undef' ) } keys %$self
}
where instead of a reference to a named sub on can directly write an anonymous sub.
As a way of solving the OP's problem, but with a different module, if you use Nice::Try instead, you will get the result you expect:
use Carp;
use Nice::Try;
try {
foo();
}
catch {
# do something before die
die $_;
} # this is line 10
sub foo {
croak 'die'; # this is line 13
}
You get:
die at ./try-catch-and-croak.pl line 13.
main::foo() called at ./try-catch-and-croak.pl line 4
main::__ANON__ called at ./try-catch-and-croak.pl line 7
eval {...} called at ./try-catch-and-croak.pl line 7 ...propagated at ./try-catch-and-croak.pl line 9.
For full disclosure, I am the author behind Nice::Try
I have written a perl program which internally calls three perl modules. My supervisor after reviewing the code asked me add global exception handling. I didn't understand what he meant by this. He also said use Eval to accomplish this.I am not sure how to use Eval so that it catches any exception in the enire perl module. Can anyone help me by providing links or by providing explanation?
Thanks in advance.
For each program he wants me to have an exception handling where in if something goes wrong it will be highlighted and it becomes easy for us to debug.
When an uncaught exception occurs, it is printed to STDERR. Your highlighting requirement is already being met.
Exceptions messages already include the line number at which they were thrown (unless specifically suppressed), so some information to help debug is already available.
$ perl -e'sub f { die "bar" } f("foo")'
bar at -e line 1.
Adding use Carp::Always; to your scripts will cause a stack backtrace to be provided as well, providing more information.
$ perl -e'use Carp::Always; sub f { die "bar" } f("foo")'
bar at -e line 1.
main::f("foo") called at -e line 1
The problem you are given seems imprecise. "Global" and eval are somewhat contradictory, as
Borodin explained in his comment. Another way to do things "global" is given in ikegami's answer. However, since mentioning eval is specific here is a rundown on a very basic use of that.
You use eval on a block of code (or an expression but that is not what you want here). If a die is thrown anywhere inside that block, the eval catches that in the sense that you get the control back, the program won't just die. The variable $# gets filled with the error message. Then you can interrogate what happened, print out diagnostics, and possibly recover from the error.
eval { run_some_code(#args) };
if ($#) {
carp "Error in `run_some_code()`: $# --";
# Do further investigation, print, recover ...
}
You can have any code in the eval block above, it needn't be a single function call. Note that eval itself returns values that convey what happened (aside from $# being set).
As for the "global" in your problem statement, one thing that comes to mind is that you use eval at the level of main:: -- wrap in it any subs that themselves invoke functions from the modules.
A crucial thing about exceptions is that they "bubble up". When a die (Perl's sole exception) is thrown in a sub and the caller doesn't eval it, it goes up the call chain ... eventually showing up in main::, and if it is not caught (eval-ed) there then the program dies. So you can eval the top-level call in main:: and get to know whether anything anywhere below went wrong.
eval { top_level_call(); };
if ($#) {
warn "Error from somewhere in `top_level_call(): $#";
}
# Functions
sub top_level_call {
# doing some work ...
another_sub();
# doing more ...
}
sub another_sub {
# do work, no eval checks
}
If an error triggering a die happens in another_sub() its processing stops immediately and the control is returned to the caller, the top_level_call(). Since that sub doesn't check (no eval there) its execution stops at that point as well, and the control returns to its caller (in this example the main:: itself). So it eventually hits main::, and eval-ing there lets you know about errors and your program won't just exit.
Perhaps that's what was meant by "global" exception handling using eval.
You can do far more along these lines, if this is what you need to be doing. See eval for starters.
Update your question with clarifications, so you get more discussion here.
In practical terms, I would say that you equip yourself with some understanding of eval use as well as some of "global" error reporting, and then ask your supervisor for clarification and/or examples, as suggested by Borodin.
I have a perl script, using standard-as-dirt Net::HTTP code, and perl 5.8.8.
I have come across an error condition in which the server returns 0 bytes of data when I call:
$_http_connection->read_response_headers;
Unfortunately, my perl script dies, because the Net::HTTP::Methods module has a "die" on line 306:
Server closed connection without sending any data back at
/usr/lib/perl5/vendor_perl/5.8.8/Net/HTTP/Methods.pm line 306
And lines 305-307 are, of course:
unless (defined $status) {
die "Server closed connection without sending any data back";
}
How can I have my script "recover gracefully" from this situation, detecting the die and subsequently going into my own error-handling code, instead of dieing itself?
I'm sure this is a common case, and probably something simple, but I have not come across it before.
Using eval to catch exceptions can occasionally be problematic, especially pre 5.14. You can use Try::Tiny.
You can use eval { } to catch die() exceptions. Use $# to inspect the thrown value:
eval {
die "foo";
};
print "the block died with $#" if $#;
See http://perldoc.perl.org/functions/eval.html for details.
Customizing the die to mean something else is simple:
sub custom_exception_handler { ... } # Define custom logic
local $SIG{__DIE__} = \&custom_exception_handler; # Won't die now
# Calls custom_exception_handler instead
The big advantage of this approach over eval is that it doesn't require calling another perl interpreter to execute the problematic code.
Of course, the custom exception handler should be adequate for the task at hand.
I'm learning Perl, and in a lot of the examples I see errors are handled like this
open FILE, "file.txt" or die $!;
Is die in the middle of a script really the best way to deal with an error?
Whether die is appropriate in the middle of the script really depends on what you're doing. If it's only tens of lines, then it's fine. A small tool with a couple hundred lines, then consider confess (see below). If it's a large object-oriented system with lots of classes and interconnected code, then maybe an exception object would be better.
confess in the Carp package:
Often the bug that led to the die isn't on the line that die reports.
Replacing die with confess (see Carp package) will give the stack trace (how we got to this line) which greatly aids in debugging.
For handling exceptions from Perl builtins, I like to use autodie. It catches failures from open and other system calls and will throw exceptions for you, without having to do the or die bit. These exceptions can be caught with a eval { }, or better yet, by using Try::Tiny.
Since I use Log::Log4perl almost everywhere, I use $logger->logdie instead of die. And if you want to have more control over your exceptions, consider Exception::Class.
It is better to catch your exceptions with Try::Tiny (see its documentation why).
Unless you've got a more specific idea, then yes you want to die when unexpected things happen.
Dying at the failure to open a file and giving the file name is better than the system telling you it can't read from or write to an anonymous undefined.
If you're talking about a "script", in general you're talking about a pretty simple piece of code. Not layers that need coordination (not usually). In a Perl Module, there is an attendant idea is that you don't own the execution environment, so either the main software cares and it catches things in an eval, OR it doesn't really care and dying would be fine. However, one you should try at a little more robustness as a module and just pass back undefs or something.
You can catch whatever dies (or croaks) in an eval block. And you can do your more specific handling there.
But if you want to inspect $! then write that code, and you'll have a more specific resolution.
Take a look at the near-universal standard of using strict. That's code that dies on questionable syntax, rather than letting you continue along.
So I think the general idea is: yes, DIE unless you have a better idea of how things should be handled. If you put enough foresight into it, you can be forgiven for the one or two times you don't die, because you know you don't need to.
The more modern approach is to use the Carp standard library.
use Carp;
my $fh;
open $fh, '<', "file.txt" or confess($!);
The main advantage is it gives a stack trace on death.
I use die but I wrap it in eval blocks for control over the error handling:
my $status = eval
{
# Some code...
};
If the 'eval' fails:
$status will be undefined.
$# will be set to whatever error message was produced (or the contents of
a die)
If the 'eval' succeeds:
$status will be the last returned value of the block.
$# will be set to ''.
As #friedo wrote, if this is a standalone script of a few lines, die is fine, but in my opinion using die in modules or require'd piece of code is not a good idea because it interrupts the flow of the program. I think the control of the flow should be a prerogative of the main part of the program.
Thus, I think, in module it is better to return undef such as return which would return undef in scalar context and an empty list in list context and set an Exception object to be retrieved for more details. This concept is implemented in the module Module::Generic like this:
# in some module
sub myfunc
{
my $self = shift( #_ );
# some code...
do{ # something } or return( $self->error( "Oops, something went wrong." ) );
}
Then, in the caller, you would write:
$obj->myfunc || die( "An error occurred at line ", $obj->error->line, " with stack trace: ", $obj->error->trace );
Here error will set an exception object and return undef.
However, because many module die or croak, you also need to catch those interruption using eval or try-catch blocks such as with Nice::Try
Full disclosure: I am the developer of both Module::Generic and Nice::Try.
Is it OK to assign to $! on an error in Perl?
E.g.,
if( ! (-e $inputfile))
{
$! = "Input file $inputfile appears to be non-existent\n";
return undef;
}
This way I can handle all errors at the top-level.
Thanks.
If you assign to $!, it is placed in the system errno variable, which only takes numbers. So you can in fact do:
use Errno "EEXIST";
$! = EEXIST;
print $!;
and get the string value for a defined system error number, but you can't do what you want - setting it to an arbitrary string. Such a string will get you a Argument "..." isn't numeric in scalar assignment warning and leave errno set to 0.
The other problem is that $! may be changed by any system call. So you can only trust it to have the value you set until you do a print or just about anything else. You probably want your very own error variable.
Well, the documentation says it's an indicator for system errors, basically. So I wouldn't assign to it, you just make your lib's users mad.
Use exceptions instead:
eval { # this ain't the evil eval
# some code
die $something;
}
if (my $err = $#) {
# exception handling
}
Note that you can "throw", or die, with about anything you need..
My Rabbi said "no!"
Setting $! is fine, but:
you should do it at the end of your function
you should return a different value that indicates that an error occurred
you should use your OS's errno values rather than strings for setting purposes
the checking code needs to check the value should do so immediately on failure of the function (and only if a failure is indicated by the function)
Something to keep in mind is that die uses the value in $! for its exit code (so long as it is not zero).
Yes you can assign stuff(#'s) to $!, just be wary of where you do it so you don't mess up some other functions message.
If you only have one variable to store errors, you'll have problems if you have more than one error occurring in your program before checking the status of your error variable. That's worth avoiding if you can help it.
Thankfully in Perl you can help it. A really nice solution is to use object-oriented exception handling from Error.pm. This module will allow you to write try/catch blocks, like this:
try {
some code;
code that might thrown an exception;
more code;
return;
}
catch Error with {
my $ex = shift; # Get hold of the exception object
# handle the exception;
};
The CPAN documentation for the module is quite good, and there is a Perl.com article on the subject too.
$! has so many caveats, being a global variable which lots of functions assign to (some of them C functions which Perl calls), that I would simply throw an exception (which in Perl means dying) and let the user trap it if they care. So instead of writing:
$obj->foo or die $!;
$obj->bar or die $!;
$obj->baz or die $!;
or even
$obj->foo or die $obj->error;
$obj->bar or die $obj->error;
$obj->baz or die $obj->error;
you can just write
$obj->foo;
$obj->bar;
$obj->baz;
and know that if there is an error you'll be informed of it. Also anyone above you will be informed and can trap it. Since that's the most common case make it happen without the user needing to remember it and type it over and over and over again.
Should you want to ignore or recover from the error, simply use eval BLOCK.
eval { $obj->foo }; # don't care if it works or not
eval { $obj->bar } or do { ...something when it doesn't work... };
Since this is the exceptional case it should be where the user has to remember to add more code and does more work.
Examples of this approach include DBI's RaiseError flag, which is only off by default for backwards compatibility, and the wonderful autodie module.