Related
I have some code that behaves rather strangely.
I am inside a function, and I declare a nested one, which should check if something isn't okay. If it's not then it should sleep for five seconds and call itself again.
sub stop {
sub wait_for_stop {
my $vm_view = shift;
if ( $vm_view->runtime->powerState->val ne "poweredOff" ) {
debug("...");
sleep(5);
wait_for_stop();
}
}
debug("Waiting for the VM to stop");
wait_for_stop( #$vm_views[0] );
}
So, in the call that results in the recursion inside the if condition, if I put the parameter (as the function definition expects it), like this:
wait_for_stop($vm_view);
I get an infinite loop.
If I leave it without a parameter, as in the code example above, it works as expected.
Shouldn't $vm_view in the subsequent calls be empty? Or the last used value ($vm_view->runtime->powerState->val)? Either case should result in unexpected behavior and error.
But it works without any parameter. So why is that? Is there something I've missed from perldoc?
EDIT1: Actually, the value of $vm_views does get changed, so that's not the reason for the infinite loop.
General clarifications
I am using the VMware SDK. The $vm_views object contains the VM details. I am polling one of its methods to detect a change, in this particular case, I need to know when the machine is turned off. So, for lack of a better way, I make a call every 5 seconds until the value is satisfactory.
My purpose is to stop the VM, make modifications that can only be made while it's off, and then launch it.
Actual question
When I don't pass a parameter, the block works as expected – it waits until the value is poweredOff (the VM is off), and continues, which doesn't make much sense, at least to me.
In the case I put $vm_view as parameter, I get an infinite loop (the value will still get changed, since I'm calling a method).
So I am wondering why the function works, when after the first call, $vm_view should be undef, and therefore, be stuck in an infinite loop? [undef ne "poweredOff" -> sleep -> recursion till death]
And why, when I pass the expected value, it gets stuck?
PS: To all those saying my recursion is weird and useless in this scenario – due to a myriad of reasons, I need to use such a format (it's better suited for my needs, since, after I get this bit working, I'll modify it to add various stuff and reuse it, and, for what I have in mind, a function seems to be the best option).
You should always look at your standard tools before going for something a little more exotic like recursion. All you need here is a while loop
It's also worth noting that #$vm_views[0] should be $$vm_views[0]) or, better, $vm_views->[0]. And you don't gain anything by defining a subroutine inside another one -- the effect is the same as if it was declared separately afterwards
An infinite loop is what I would expect if $vm_view->runtime->powerState->val never returns poweredOff, and the code below won't fix that. I don't see any code that tells the VM to stop before you wait for the status change. Is that correct?
I don't understand why you say that your code works correctly when you call wait_for_stop without any parameters. You will get the fatal error
Can't call method "runtime" on an undefined value
and your program will stop. Is what you have posted the real code?
This will do what you intended. I also think it's easier to read
use strict;
use warnings;
my $vm_views;
sub stop {
debug ("Waiting for the VM to stop");
my $vm_view = $vm_views->[0];
while ( $vm_view->runtime->powerState->val ne 'poweredOff' ) {
debug('...');
sleep 5;
}
}
I think you would have a better time not calling wait_for_stop() recursively. This way might serve you better:
sub stop
{
sub wait_for_stop
{
my $vm_view = shift;
if ($vm_view->runtime->powerState->val ne "poweredOff")
{
debug("...");
#sleep(5);
#wait_for_stop();
return 0;
}
return 1;
}
debug ("Waiting for the VM to stop");
until(wait_for_stop(#$vm_views[0]))
{
sleep(5);
}
}
Your old way was rather confusing and I don't think you were passing the $vm_view variable through to the recursive subroutine call.
Update:
I tried reading it here:
https://www.vmware.com/support/developer/viperltoolkit/doc/perl_toolkit_guide.html#step3
It says:
When the script is run, the VI Perl Toolkit runtime checks the
environment variables, configuration file contents, and command-line
entries (in this order) for the necessary connection-setup details. If
none of these overrides are available, the runtime uses the defaults
(see Table 1 ) to setup the connection.
So, the "runtime" is using the default connection details even when a vm object is not defined? May be?
That still doesn't answer why it doesn't work when the parameter is passed.
You need to understand the VM SDK better. You logic for recursion and usage of function parameters are fine.
Also, the page: https://www.vmware.com/support/developer/viperltoolkit/doc/perl_toolkit_guide.html
says -
VI Perl Toolkit views have several characteristics that you should
keep in mind as you write your own scripts. Specifically, a view:
Is a Perl object
Includes properties and methods that correlate to the properties and
operations of the server-side managed object
Is a static copy of one or more server-side managed objects, and as
such (static), is not updated automatically as the state of objects
on the server changes.
So what the "vm" function returns is a static copy, which can be updated from the script. May be it is getting updated when you make a call while passing the $vm_view?
Old Answer:
Problem is not what you missed from Perl docs. The problem is with your understanding of recursion.
The purpose of recursion is to keep running until $vm_view->runtime->powerState->val becomes "PoweredOff" and then cascade back. If you don't update the value, it keeps running forever.
When you say:
I get an infinite loop.
Are you updating the $vm_view within the if condition?
Otherwise, the variable is same every time you call the function and hence you can end up in infinite loop.
If I leave it without a parameter, as in the code example above, it
works as expected.
How can it work as expected? What is expected? There is no way the function can know what value your $vm_view is being updated with.
I have simplified the code, added updating a simple variable (similar to your $vm_view) and tested. Use this to understand what is happening:
sub wait_for_stop
{
my $vm_view = shift;
if ($vm_view < 10){
print "debug...\n";
sleep(5);
$vm_view++; // update $vm_view->runtime->powerState->val here
// so that it becomes "poweredOff" at some point of time
// and breaks the recursion
wait_for_stop($vm_view);
}
}
wait_for_stop(1);
Let me know in comments how the variable is being updated and I will help resolve.
I use Log4perl in one of my applications and created my own appender which inherits from Log::Dispatch::Email because I need some special handling of sendmail. This appender worked for some years now, but today I recognized some weird behavior in which $# doesn't get set as before if I configure Log4perl to use my appender or simply Log::Dispatch::Email itself. I used to catch errors in the following way:
eval { main(); 1; };
if (my $error = $#)
{
log()->error($error);
exit(error_no_success());
}
exit(error_success());
If I remove the mail appender from my Log4perl configuration and my application dies in main, $error gets the message and it gets logged within the alternative. The problem now is that when I configure my own descendant of Log::Dispatch::Email or this abstract base class directly, $# in the above statement is the empty string, resulting in the same error as before isn't recognized anymore. If I write something like eval {} or ... $# is properly available and can be saved. The following works:
my $error = undef;
eval { main(); 1; } or $error = $#;
my $error2 = $#;
if ($error)
{
log()->error($error);
exit(error_no_success());
}
exit(error_success());
$error2 is always the empty string if I configure Log::Dispatch::Email in any way. Of course I don't want to change all my code which uses the first example and used to work before to the second one.
Is there anything wrong with my first example? From my point of view it looks like documented for eval in perldoc and it works without email appenders.
Can you think of any reason why using mail appenders changes the behavior on how or when or whatever Perl sets $# in my second example? Any workarounds? I already had a look at the sources of Log::Dispatch but couldn't find anything obviously interfering with my code.
Thanks for any hints!
With some help over on PerlMonks I finally found the problem: $# is unreliable. I already had similar problems before and localized $# in all my destructors by convention, obviously I missed one, which used to log some debug output. After localizing $# in this destructor before any logging statements, too, my problem got solved and error trapping worked again. I don't know why the problem only got triggered using Log::Dispatch, as the destructor always logged debug statements before, but whatever... Like suggested on PerlMonks, one should switch to use Devel::EvalError in the future.
I am converting some cgi scripts to mod_perl. Under cgi, I used a sig DIE to capture stack traces whenever there was an uncaptured exception, and logged them. This worked great: whenever something died in the script, I'd get a nice stack trace in my application logs. Code is:
BEGIN {
$SIG{__DIE__} = \&sigDie;
}
sub sigDie {
return 1 if $^S; # we are in an eval block
my ($error) = #_;
cluck("Caught fatal error: $error"); # put a stack trace in the logs via warn
local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1;
FATAL #_; # call log4perl's fatal
return 1;
}
Under Apache2::Registry, however, my code is no longer called, it simply stops logging when it dies. I assumed this was because my code is being eval'ed by mod_perl, but I took the eval check off my routine above and I'm still not getting called.
Is there any way I can get what I want under mod_perl? I have found these automatic logging of stack traces immensely useful and would miss them if I have to forgo them. So far I have come up empty on how to get it.
I don't know the answer, but can think of a few possibilities and ways to check.
Something is wrong with log4perl.
Does a call to FATAL still work outside of a __DIE__ handler?
Errors are not being logged at all.
Remove the die handler, do exceptions get logged?
Something is replacing your $SIG{__DIE__} handler.
Since you're setting it up at BEGIN time, it's possible something either in Apache2::Registry or another program is replacing it. I'd find out by verifying what is in $SIG{__DIE__} just before throwing an error. Perhaps dumping it out with Data::Dump::Streamer, which can handle code refs, you might be able to figure out what's setting it.
A safer, and more polite, way to register a die handler is...
local $SIG{__DIE__} = ...;
...the rest of your program...
This will re-register your handler on each request AND not blow over a global handler outside of its scope.
Hope that helps to figure out what's going on.
A discussion in another question got me wondering: what do other programming languages' exception systems have that Perl's lacks?
Perl's built-in exceptions are a bit ad-hoc in that they were, like the Perl 5 object system, sort-of bolted on as an afterthought, and they overload other keywords (eval and die) which are not dedicated specifically to exceptions.
The syntax can be a little ugly, compared to languages with builtin try/throw/catch type syntax. I usually do it like this:
eval {
do_something_that_might_barf();
};
if ( my $err = $# ) {
# handle $err here
}
There are several CPAN modules that provide syntactic sugar to add try/catch keywords and to allow the easy declaration of exception class hierarchies and whatnot.
The main problem I see with Perl's exception system is the use of the special global $# to hold the current error, rather than a dedicated catch-type mechanism that might be safer, from a scope perspective, though I've never personally run into any problems with $# getting munged.
The typical method most people have learned to handle exceptions is vulnerable to missing trapped exceptions:
eval { some code here };
if( $# ) { handle exception here };
You can do:
eval { some code here; 1 } or do { handle exception here };
This protects from missing the exception due to $# being clobbered, but it is still vulnerable to losing the value of $#.
To be sure you don't clobber an exception, when you do your eval, you have to localize $#;
eval { local $#; some code here; 1 } or do { handle exception here };
This is all subtle breakage, and prevention requires a lot of esoteric boilerplate.
In most cases this isn't a problem. But I have been burned by exception eating object destructors in real code. Debugging the issue was awful.
The situation is clearly bad. Look at all the modules on CPAN built provide decent exception handling.
Overwhelming responses in favor of Try::Tiny combined with the fact that Try::Tiny is not "too clever by half", have convinced me to try it out. Things like TryCatch and Exception::Class::TryCatch, Error, and on and on are too complex for me to trust. Try::Tiny is a step in the right direction, but I still don't have a lightweight exception class to use.
Try::Tiny (or modules built on top of it) is the only correct way to deal with exceptions in Perl 5. The issues involved are subtle, but the linked article explains them in detail.
Here's how to use it:
use Try::Tiny;
try {
my $code = 'goes here';
succeed() or die 'with an error';
}
catch {
say "OH NOES, YOUR PROGRAM HAZ ERROR: $_";
};
eval and $# are moving parts you don't need to concern yourself with.
Some people think this is a kludge, but having read the implementations of other languages (as well as Perl 5), it's no different than any other. There is just the $# moving part that you can get your hand caught in... but as with other pieces of machinery with exposed moving parts... if you don't touch it, it won't rip off your fingers. So use Try::Tiny and keep your typing speed up ;)
Some exception classes, e.g. Error, cannot handle flow control from within try/catch blocks. This leads to subtle errors:
use strict; use warnings;
use Error qw(:try);
foreach my $blah (#somelist)
{
try
{
somemethod($blah);
}
catch Error with
{
my $exception = shift;
warn "error while processing $blah: " . $exception->stacktrace();
next; # bzzt, this will not do what you want it to!!!
};
# do more stuff...
}
The workaround is to use a state variable and check that outside the try/catch block, which to me looks horribly like stinky n00b code.
Two other "gotchas" in Error (both of which have caused me grief as they are horrible to debug if you haven't run into this before):
use strict; use warnings;
try
{
# do something
}
catch Error with
{
# handle the exception
}
Looks sensible, right? This code compiles, but leads to bizarre and unpredictable errors. The problems are:
use Error qw(:try) was omitted, so the try {}... block will be misparsed (you may or may not see a warning, depending on the rest of your code)
missing semicolon after the catch block! Unintuitive as control blocks do not use semicolons, but in fact try is a prototyped method call.
Oh yeah, that also reminds me that because try, catch etc are method calls, that means that the call stack within those blocks will not be what you expect. (There's actually two extra stack levels because of an internal call inside Error.pm.) Consequently, I have a few modules full of boilerplate code like this, which just adds clutter:
my $errorString;
try
{
$x->do_something();
if ($x->failure())
{
$errorString = 'some diagnostic string';
return; # break out of try block
}
do_more_stuff();
}
catch Error with
{
my $exception = shift;
$errorString = $exception->text();
}
finally
{
local $Carp::CarpLevel += 2;
croak "Could not perform action blah on " . $x->name() . ": " . $errorString if $errorString;
};
A problem I recently encountered with the eval exception mechanism has to do with the $SIG{__DIE__} handler. I had -- wrongly -- assumed that this handler only gets called when the Perl interpreter is exited through die() and wanted to use this handler for logging fatal events. It then turned out that I was logging exceptions in library code as fatal errors which clearly was wrong.
The solution was to check for the state of the $^S or $EXCEPTIONS_BEING_CAUGHT variable:
use English;
$SIG{__DIE__} = sub {
if (!$EXCEPTION_BEING_CAUGHT) {
# fatal logging code here
}
};
The problem I see here is that the __DIE__ handler is used in two similar but different situations. That $^S variable very much looks like a late add-on to me. I don't know if this is really the case, though.
With Perl, language and user-written exceptions are combined: both set $#. In other languages language exceptions are separate from user-written exceptions and create a completely separate flow.
You can catch the base of user written exceptions.
If there is My::Exception::one and My::Exception::two
if ($# and $#->isa('My::Exception'))
will catch both.
Remember to catch any non-user exceptions with an else.
elsif ($#)
{
print "Other Error $#\n";
exit;
}
It's also nice to wrap the exception in a sub call the sub to throw it.
In C++ and C#, you can define types that can be thrown, with separate catch blocks that manage each type. Perl type systems have certain niggling issues related to RTTI and inheritance, according from what I read on chomatic's blog.
I'm not sure how other dynamic languages manage exceptions; both C++ and C# are static languages and that bears with it a certain power in the type system.
The philosophical problem is that Perl 5 exceptions are bolted on; they aren't built from the start of the language design as something integral to how Perl is written.
It has been a looong time since I used Perl, so my memory may be fuzzy and/or Perl may have improved, but from what I recall (in comparison with Python, which I use on a daily basis):
since exceptions are a late addition, they are not consistently supported in the core libraries
(Not true; they are not consistently supported in core libraries because the programmers that wrote those libraries don't like exceptions.)
there is no predefined hierarchy of exceptions - you can't catch a related group of exceptions by catching the base class
there is no equivalent of try:... finally:... to define code that will be called regardless of whether an exception was raised or not, e.g. to free up resources.
(finally in Perl is largely unnecessary -- objects' destructors run immediately after scope exit; not whenever there happens to be memory pressure. So you can actually deallocate any non-memory resources in your destructor, and it will work sanely.)
(as far as I can tell) you can only throw strings - you can't throw objects that have additional information
(Completely false. die $object works just as well as die $string.)
you cant get a stack trace showing you where the exception was thrown - in python you get detailed information including the source code for each line in the call stack
(False. perl -MCarp::Always and enjoy.)
it is a butt-ugly kludge.
(Subjective. It's implemented the same way in Perl as it is everywhere else. It just uses differently-named keywords.)
Don't use Exceptions for regular errors. Only Fatal problems that will stop the current execution should die. All other should be handled without die.
Example: Parameter validation of called sub: Don't die at the first problem. Check all other parameters and then decide to stop by returning something or warn and correct the faulty parameters and proceed. That do in test or development mode. But possibly die in production mode. Let the application decide this.
JPR (my CPAN login)
Greetings from Sögel, Germany
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
How can I cleanly handle error checking in Perl?
What’s broken about exceptions in Perl?
I saw code which works like this:
do_something($param) || warn "something went wrong\n";
and I also saw code like this:
eval {
do_something_else($param);
};
if($#) {
warn "something went wrong\n";
}
Should I use eval/die in all my subroutines? Should I write all my code based on stuff returned from subroutines? Isn't eval'ing the code ( over and over ) gonna slow me down?
Block eval isn't string eval, so no, it's not slow. Using it is definitely recommended.
There are a few annoying subtleties to the way it works though (mostly annoying side-effects of the fact that $# is a global variable), so consider using Try::Tiny instead of memorizing all of the little tricks that you need to use eval defensively.
do_something($param) || warn "something went wrong\n";
In this case, do_something is expected to return an error code if something goes wrong. Either it can't die or if it does, it is a really unusual situation.
eval {
do_something_else($param);
};
if($#) {
warn "something went wrong\n";
}
Here, the assumption is that the only mechanism by which do_something_else communicates something going wrong is by throwing exceptions.
If do_something_else throws exceptions in truly exceptional situations and returns an error value in some others, you should also check its return value.
Using the block form of eval does not cause extra compilation at run time so there are no serious performance drawbacks:
In the second form, the code within the BLOCK is parsed only once--at the same time the code surrounding the eval itself was parsed--and executed within the context of the current Perl program. This form is typically used to trap exceptions more efficiently than the first (see below), while also providing the benefit of checking the code within BLOCK at compile time.
Modules that warn are very annoying. Either succeed or fail. Don't print something to the terminal and then keep running; my program can't take action based on some message you print. If the program can keep running, only print a message if you have been explicitly told that it's ok. If the program can't keep running, die. That's what it's for.
Always throw an exception when something is wrong. If you can fix the problem, fix it. If you can't fix the problem, don't try; just throw the exception and let the caller deal with it. (And if you can't handle an exception from something you call, don't.)
Basically, the reason many programs are buggy is because they try to fix errors that they can't. A program that dies cleanly at the first sign of a problem is easy to debug and fix. A program that keeps running when it's confused just corrupts data and annoys everyone. So don't do that. Die as soon as possible.
Your two examples do entirely different things. The first checks for a false return value, and takes some action in response. The second checks for an actual death of the called code.
You'll have to decide for yourself which action is appropriate in each case. I would suggest simply returning false in most circumstances. You should only be explicitly dieing if you have encountered errors so severe that you cannot continue (or there is no point in continuing, but even then you could still return false).
Wrapping a block in eval {} is not the same thing as wrapping arbitrary code in eval "". In the former case, the code is still parsed at compile-time, and you do not incur any extra overhead. You will simply catch any death of that code (but you won't have any indication as to what went wrong or how far you got in your code, except for the value that is left for you in $#). In the latter case, the code is treated as a simple string by the Perl interpreter until it is actually evaluated, so there is a definite cost here as the interpreter is invoked (and you lose all compile-time checking of your code).
Incidentally, the way you called eval and checked for the value of $# is not a recommended form; for an extensive discussion of exception gotchas and techniques in Perl, see this discussion.
The first version is very "perlish" and pretty straightforward to understand. The only drawback of this idiom is that it is readable only for short cases. If error handling needs more logic, use the second version.
Nobody's really addressed the "best practice" part of this yet, so I'll jump in.
Yes, you should definitely throw an exception in your code when something goes wrong, and you should do it as early as possible (so you limit the code that needs to be debugged to work out what's causing it).
Code that does stuff like return undef to signify failure isn't particularly reliable, simply because people will tend to use it without checking for the undef returnvalue - meaning that a variable they assume has something meaningful in it actually may not. This leads to complicated, hard to debug problems, and even unexpected problems cropping up later in previously-working code.
A more solid approach is to write your code so that it dies if something goes wrong, and then only if you need to recover from that failure, wrap the any calls to it in eval{ .. } (or, better, try { .. } catch { .. } from Try::Tiny, as has been mentioned). In most cases, there won't be anything meaningful that the calling code can do to recover, so calling code remains simple in the common case, and you can just assume you'll get a useful value back. If something does go wrong, then you'll get an error message from the actual part of the code that failed, rather than silently getting an undef. If your calling code can do something to recover failures, then it can arrange to catch exceptions and do whatever it needs to.
Something that's worth reading about is Exception classes, which are a structured way to send extra information to calling code, as well as allow it to pick which exceptions it wants to catch and which it can't handle. You probably won't want to use them everywhere in your code, but they're a useful technique when you have something complicated that can fail in equally complicated ways, and you want to arrange for failures to be recoverable.