Hi!

Please note that true value in $@ is *not* necessary condition for
checking if error in eval occurred. And similarly empty string or logic
false value in $@ is *not* necessary condition that eval succeeded.

The only thing which is guaranteed is undef return value from eval in
case it failed. So correct check is:

my $success = eval {
  # MY CODE
  1;
};

unless ($success) {
  # HANDLE ERROR, $@ may (but does not have to) contain error
}

"1;" in eval block is there to set $success to 1. In case MY CODE throw
error, $success is set to undef by perl.

Note that $@ is propagated back, so you should localize $@ before
calling eval. This is especially required if MY CODE (or function called
from MY CODE) calls also eval.

So you can use this pattern:

{
  local $@;
  eval {
    # MY CODE
    1;
  } or do {
    # HANDLE ERROR in $@ (but may be undef!)
  };
}

If you do not write 1; then return value is taken from the last call in
MY CODE. So if problem is also when last function return non zero, then
you can remove "1;". You can also combine it with "and" block, but
beware for and/or logical blocks:

{
  local $@;
  eval {
    func_which_may_die_or_fail_with_zero();
  } and do {
    print "function succeeded\n";
    func_may_fail_with_zero();
  } or do {
    my $err = $@ || 'unknown error';
    warn "Error: $err\n";
    rollback();
  };
}

But I suggest to use module like Try::Tiny or Try::Catch which handle
above eval and $@ logic for you and you can easily write:

try {
  # MY CODE
} catch {
  # HANDLE ERROR in $_ (may be undef!)
  my $err = $_ || 'unknown error';
};

On Tuesday 30 May 2017 09:39:53 John Dunlap wrote:
> Yes, I do that extensively and it works perfectly. It's as close to a true
> Try/Catch block as we have in the perl world. However, I *usually* do not
> return values from it because I use this construct to control my database
> transaction demarcation and using the return value from outside of the eval
> wouldn't be inside the transaction. With that said, I have had to do it
> from time to time and it works just fine. Also, it is advisable to copy the
> contents of $@ into a separate variable immediately. My understanding is
> that this can prevent some weird concurrency issues, under some conditions.
> My general form looks something like this,
> 
> my $return = eval {
>     # BEGIN DATABASE TRANSACTION
> 
>     # DO SOME STUFF
> 
>     # COMMIT DATA BASE TRANSACTION
> 
>     return 'SOME VALUE';
> };
> 
> if ($@) {
>     my $error = $@;
> 
>     # ROLLBACK DATABASE TRANSACTION
> 
>     # LOG ERROR
> }
> 
> 
> On Tue, May 30, 2017 at 4:47 AM, James Smith <j...@sanger.ac.uk> wrote:
> 
> > Not really a mod_perl question but you can always wrap your method call in
> > an eval
> >
> > my $ret = eval { $m->...() };
> >
> > And then check $@ for the error message
> >
> >
> > On 2017-05-26 02:08 AM, Peng Yonghua wrote:
> >
> >> greeting,
> >>
> >> I am not so good at perl/modperl,:)
> >>
> >> In the handler, a method from a class was called, when something dies
> >> from within the method, what's the correct way the handler will take?
> >>
> >> for example, I wrote this API which works right if given a correct domain
> >> name:
> >>
> >> http://fenghe.org/domain/?d=yahoo.com
> >>
> >> server response:
> >> var data={"registration":"domain may be taken","domain":"yahoo.com"}
> >>
> >> If given a wrong domain name:
> >>
> >> http://fenghe.org/domain/?d=yahoo.nonexist
> >>
> >> The server returns 500.
> >>
> >> This is because, in the handler, I used this module (wrote also by me):
> >>
> >> http://search.cpan.org/~pyh/Net-Domain-Registration-Check-0.
> >> 03/lib/Net/Domain/Registration/Check.pm
> >>
> >> And in the module, croak like this was happened,
> >>
> >> croak "domain TLD not exists" unless tld_exists($tld);
> >>
> >> When handler meets the croak, it dies (I guess) and server returns 500.
> >>
> >> How will I make the full system work right? fix on handler, or the module
> >> itself?
> >>
> >> Thanks.
> >>
> >
> >
> >
> > --
> > The Wellcome Trust Sanger Institute is operated by Genome Research
> > Limited, a charity registered in England with number 1021457 and a company
> > registered in England with number 2742969, whose registered office is 215
> > Euston Road, London, NW1 2BE.
> 
> 
> 
> 
> -- 
> John Dunlap
> *CTO | Lariat *
> 
> *Direct:*
> *j...@lariat.co <j...@lariat.co>*
> 
> *Customer Service:*
> 877.268.6667
> supp...@lariat.co

Reply via email to