Signals and local $@

Discussion in 'Perl Misc' started by Adrien BARREAU, May 24, 2013.

  1. Hello all.


    I'm trying to write a little wrapper which properly handles a call with
    a timeout.

    Since I'm on a 5.10.1, I take care of all eval{} pitfalls I know (more
    or less take some parts of Try::Tiny ideas just to do a proper eval).

    Here is the thing I don't know how to deal with.

    # ---
    #!/usr/bin/perl

    use strict;
    use warnings;

    sub sleep10
    {
    local $@;
    sleep 10;
    }

    {
    eval {
    local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    alarm 2;
    sleep10();
    };

    alarm 0;
    print "Err: $@\n";
    }
    # ---

    That script does its timeout after 2 seconds, but prints "Err :".
    I don't find a way not to loose my handler error message if the code I
    try to protect localize $@.
    I don't even know if I have a chance to achieve that.

    Might somebody help me a bit about that? :)

    Thanks.
    Adrien.
    Adrien BARREAU, May 24, 2013
    #1
    1. Advertising

  2. Adrien BARREAU

    Dr.Ruud Guest

    On 24/05/2013 13:05, Adrien BARREAU wrote:
    > Hello all.
    >
    >
    > I'm trying to write a little wrapper which properly handles a call with
    > a timeout.
    >
    > Since I'm on a 5.10.1, I take care of all eval{} pitfalls I know (more
    > or less take some parts of Try::Tiny ideas just to do a proper eval).
    >
    > Here is the thing I don't know how to deal with.
    >
    > # ---
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > sub sleep10
    > {
    > local $@;
    > sleep 10;
    > }
    >
    > {
    > eval {
    > local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    > alarm 2;
    > sleep10();
    > };
    >
    > alarm 0;
    > print "Err: $@\n";
    > }
    > # ---
    >
    > That script does its timeout after 2 seconds, but prints "Err :".
    > I don't find a way not to loose my handler error message if the code I
    > try to protect localize $@.
    > I don't even know if I have a chance to achieve that.
    >
    > Might somebody help me a bit about that? :)


    You are doing many things wrong in the above. Try::Tiny is meant for
    coders that don't know how to do it properly, so why don't you just use
    that?

    Be aware that (the value of) $@ has no meaning, unless there has been an
    error detected.


    my $ok;

    eval {
    $ok = can_die();
    1; # success
    }
    or do {
    my $eval_error = $@ || 'Zombie Error';
    warn $eval_error;
    };

    So only use $@ when eval{} tells you that you can.


    --
    Ruud

    In stead of 'local $@', consider push @@, $@;
    Dr.Ruud, May 24, 2013
    #2
    1. Advertising

  3. On 05/24/2013 03:08 PM, Dr.Ruud wrote:
    > On 24/05/2013 13:05, Adrien BARREAU wrote:
    >> Hello all.
    >>
    >>
    >> I'm trying to write a little wrapper which properly handles a call with
    >> a timeout.
    >>
    >> Since I'm on a 5.10.1, I take care of all eval{} pitfalls I know (more
    >> or less take some parts of Try::Tiny ideas just to do a proper eval).
    >>
    >> Here is the thing I don't know how to deal with.
    >>
    >> # ---
    >> #!/usr/bin/perl
    >>
    >> use strict;
    >> use warnings;
    >>
    >> sub sleep10
    >> {
    >> local $@;
    >> sleep 10;
    >> }
    >>
    >> {
    >> eval {
    >> local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    >> alarm 2;
    >> sleep10();
    >> };
    >>
    >> alarm 0;
    >> print "Err: $@\n";
    >> }
    >> # ---
    >>
    >> That script does its timeout after 2 seconds, but prints "Err :".
    >> I don't find a way not to loose my handler error message if the code I
    >> try to protect localize $@.
    >> I don't even know if I have a chance to achieve that.
    >>
    >> Might somebody help me a bit about that? :)

    >
    > You are doing many things wrong in the above. Try::Tiny is meant for
    > coders that don't know how to do it properly, so why don't you just use
    > that?


    Well, at first, if I never learn, I'll never know, will I?
    And I can not install Try::Tiny. If it had been an option, I wouldn't
    have tried by myself.

    >
    > Be aware that (the value of) $@ has no meaning, unless there has been an
    > error detected.
    >
    >
    > my $ok;
    >
    > eval {
    > $ok = can_die();
    > 1; # success
    > }
    > or do {
    > my $eval_error = $@ || 'Zombie Error';
    > warn $eval_error;
    > };
    >
    > So only use $@ when eval{} tells you that you can.
    >
    >


    I'm not thinking something else.
    It seems that my code works, and follows the same pattern you just wrote.

    The only thing that troubles me is the very case I wrote: if "can_die()"
    localize $@ and receive a signal that makes it die.


    Thanks for responding :).
    Adrien BARREAU, May 24, 2013
    #3
  4. Adrien BARREAU

    Dr.Ruud Guest

    On 24/05/2013 16:13, Adrien BARREAU wrote:
    > On 05/24/2013 03:08 PM, Dr.Ruud wrote:


    >> So only use $@ when eval{} tells you that you can.

    >
    > I'm not thinking something else.


    Your code shows differently.


    > It seems that my code works, and follows the same pattern you just wrote.


    It doesn't.


    > The only thing that troubles me is the very case I wrote: if "can_die()"
    > localize $@ and receive a signal that makes it die.


    If that troubles you, then go and find out what localize does.
    After that: Why are you localizing $@?

    --
    Ruud
    Dr.Ruud, May 24, 2013
    #4
  5. On 05/24/2013 04:36 PM, Ben Morrow wrote:
    >
    > Quoth Adrien BARREAU<>:
    >> On 05/24/2013 03:08 PM, Dr.Ruud wrote:
    >>> On 24/05/2013 13:05, Adrien BARREAU wrote:
    >>>>
    >>>> Since I'm on a 5.10.1, I take care of all eval{} pitfalls I know (more
    >>>> or less take some parts of Try::Tiny ideas just to do a proper eval).
    >>>
    >>> You are doing many things wrong in the above. Try::Tiny is meant for
    >>> coders that don't know how to do it properly, so why don't you just use
    >>> that?

    >>
    >> Well, at first, if I never learn, I'll never know, will I?
    >> And I can not install Try::Tiny. If it had been an option, I wouldn't
    >> have tried by myself.

    >
    > Try::Tiny is one .pm file. If you can run perl at all you can install it
    > somewhere and add that somewhere to @INC.
    >
    > Ben
    >


    Of course, but this is meant to run on some computer where adding new
    CPAN files is not an option.
    That's not my choice and I can't help it.

    So it became a precondition: I must do without it.


    Adrien.
    Adrien BARREAU, May 24, 2013
    #5
  6. On 05/24/2013 04:51 PM, Dr.Ruud wrote:
    > On 24/05/2013 16:13, Adrien BARREAU wrote:
    >> On 05/24/2013 03:08 PM, Dr.Ruud wrote:

    >
    >>> So only use $@ when eval{} tells you that you can.

    >>
    >> I'm not thinking something else.

    >
    > Your code shows differently.
    >
    >
    >> It seems that my code works, and follows the same pattern you just wrote.

    >
    > It doesn't.
    >
    >
    >> The only thing that troubles me is the very case I wrote: if "can_die()"
    >> localize $@ and receive a signal that makes it die.

    >
    > If that troubles you, then go and find out what localize does.
    > After that: Why are you localizing $@?
    >


    My introduction was: "I'm trying to write a little wrapper which
    properly handles a call with a timeout.".
    Some forgotten detail: "a call" meant "a call I don't write".
    It's meant to be a little part of some API, somewhere.

    I found that, if there is a localization of $@ in "the call", my wrapper
    fails.

    I'm trying to figure if I can do better. Nothing more.

    Adrien.
    Adrien BARREAU, May 24, 2013
    #6
  7. "Dr.Ruud" <> writes:

    [...]

    > Be aware that (the value of) $@ has no meaning, unless there has been
    > an error detected.


    Please be aware of the fact that this it absolute, total, utter
    rubbish, cf

    If there is a syntax error or runtime error, or a "die"
    statement is executed, "eval" returns an undefined value in
    scalar context or an empty list in list context, and $@ is set
    to the error message. If there was no error, $@ is guaranteed
    to be a null string.
    [perdoc -f eval]

    In particular, eval might return 'an undefined value or an empty list'
    for other reasons than 'an error occured', namely, when the last
    statement executed by the eval returned undef.
    Rainer Weikusat, May 24, 2013
    #7
  8. Adrien BARREAU <> writes:

    [...]

    > I'm trying to write a little wrapper which properly handles a call
    > with a timeout.
    >
    > Since I'm on a 5.10.1, I take care of all eval{} pitfalls I know (more
    > or less take some parts of Try::Tiny ideas just to do a proper eval).
    >
    > Here is the thing I don't know how to deal with.
    >
    > # ---
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > sub sleep10
    > {
    > local $@;
    > sleep 10;
    > }
    >
    > {
    > eval {
    > local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    > alarm 2;
    > sleep10();
    > };
    >
    > alarm 0;
    > print "Err: $@\n";
    > }
    > # ---
    >
    > That script does its timeout after 2 seconds, but prints "Err :".


    This is inherently racy: With your code above, the SIGALRM could
    happend after the handler was deinstalled when exiting the eval but
    before the running alarm was cancelled. This would the terminate the
    process because the default action for SIGALRM would occur.

    The problem with $@ being cleared can be fixed by removing the 'local $@'
    from the sleep10 routine:

    ----------------
    #!/usr/bin/perl

    use strict;
    use warnings;

    sub sleep10
    {
    sleep 10;
    }

    {
    eval {
    local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    alarm 2;
    sleep10();
    };

    alarm 0;
    print "Err: $@\n";
    };
    ----------------

    because otherwise, assuming the die is executed while sleep10 is
    'running', it will modifiy the localized version of $@.
    Rainer Weikusat, May 24, 2013
    #8
  9. On 05/24/2013 05:46 PM, Rainer Weikusat wrote:
    >
    > This is inherently racy: With your code above, the SIGALRM could
    > happend after the handler was deinstalled when exiting the eval but
    > before the running alarm was cancelled. This would the terminate the
    > process because the default action for SIGALRM would occur.
    >
    > The problem with $@ being cleared can be fixed by removing the 'local $@'
    > from the sleep10 routine:
    >
    > ----------------
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > sub sleep10
    > {
    > sleep 10;
    > }
    >
    > {
    > eval {
    > local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    > alarm 2;
    > sleep10();
    > };
    >
    > alarm 0;
    > print "Err: $@\n";
    > };
    > ----------------
    >
    > because otherwise, assuming the die is executed while sleep10 is
    > 'running', it will modifiy the localized version of $@.


    That's what I thought, but I hoped to find a way to protect it.
    As far as I understand, none exists. Is that true?
    Adrien BARREAU, May 24, 2013
    #9
  10. Adrien BARREAU <> writes:
    > On 05/24/2013 05:46 PM, Rainer Weikusat wrote:
    >> This is inherently racy: With your code above, the SIGALRM could
    >> happend after the handler was deinstalled when exiting the eval but
    >> before the running alarm was cancelled. This would the terminate the
    >> process because the default action for SIGALRM would occur.
    >>
    >> The problem with $@ being cleared can be fixed by removing the 'local $@'
    >> from the sleep10 routine:
    >>
    >> ----------------
    >> #!/usr/bin/perl
    >>
    >> use strict;
    >> use warnings;
    >>
    >> sub sleep10
    >> {
    >> sleep 10;
    >> }
    >>
    >> {
    >> eval {
    >> local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    >> alarm 2;
    >> sleep10();
    >> };
    >>
    >> alarm 0;
    >> print "Err: $@\n";
    >> };
    >> ----------------
    >>
    >> because otherwise, assuming the die is executed while sleep10 is
    >> 'running', it will modifiy the localized version of $@.

    >
    > That's what I thought, but I hoped to find a way to protect it.
    > As far as I understand, none exists. Is that true?


    *If* the die is executed while a scope with a localized $@ is active,
    it will change the value of the localized $@ and this change will be
    undone as part of the stack-unwinding which happens when exiting that
    scope.
    Rainer Weikusat, May 24, 2013
    #10
  11. On 05/24/2013 07:21 PM, Rainer Weikusat wrote:
    >>>
    >>> because otherwise, assuming the die is executed while sleep10 is
    >>> 'running', it will modifiy the localized version of $@.

    >>
    >> That's what I thought, but I hoped to find a way to protect it.
    >> As far as I understand, none exists. Is that true?

    >
    > *If* the die is executed while a scope with a localized $@ is active,
    > it will change the value of the localized $@ and this change will be
    > undone as part of the stack-unwinding which happens when exiting that
    > scope.
    >


    Thank you for your answers :).

    Adrien.
    Adrien BARREAU, May 24, 2013
    #11
  12. On 05/24/2013 06:54 PM, Ben Morrow wrote:
    >
    > Quoth Adrien BARREAU<>:
    >> On 05/24/2013 04:36 PM, Ben Morrow wrote:
    >>>
    >>> Try::Tiny is one .pm file. If you can run perl at all you can install it
    >>> somewhere and add that somewhere to @INC.

    >>
    >> Of course, but this is meant to run on some computer where adding new
    >> CPAN files is not an option.
    >> That's not my choice and I can't help it.
    >>
    >> So it became a precondition: I must do without it.

    >
    > So copy the code out of Try/Tiny.pm into your own script.
    >
    > More generally, this sort of restriction can usually be worked around
    > with a little thought, and it's usually worth doing so. For instance,
    > PAR::packer provides the pp utility, and pp -P will pack a script and
    > any pure-Perl modules it uses into a single Perl file. (It doesn't
    > always work perfectly--some modules do some rather strange things--but
    > it works well for simple cases.)
    >
    > Ben
    >

    Once again, I agree about that idea, but I'm not allowed to do that either.
    I'll take a look to PAR, you described some interesting stuff (for other
    developments).

    Thanks :).
    Adrien BARREAU, May 24, 2013
    #12
  13. On 05/24/2013 06:58 PM, Ben Morrow wrote:
    >
    > Quoth Adrien BARREAU<>:
    >>
    >> My introduction was: "I'm trying to write a little wrapper which
    >> properly handles a call with a timeout.".
    >> Some forgotten detail: "a call" meant "a call I don't write".
    >> It's meant to be a little part of some API, somewhere.
    >>
    >> I found that, if there is a localization of $@ in "the call", my wrapper
    >> fails.
    >>
    >> I'm trying to figure if I can do better. Nothing more.

    >
    > If you must work around this sort of thing, you can do so by using your
    > own variable:
    >
    > sub make_call {
    > my $alarmed;
    > $SIG{ALRM} = sub { $alarmed = 1 };
    > try { ... }
    > catch {
    > if ($alarmed) { ... }
    > };
    > }
    >
    > IMHO code which localises $@ without rethrowing any exceptions it
    > doesn't handle is broken, and you would be better off simply documenting
    > that this doesn't work.
    >
    > Ben
    >

    I did not think about that variable idea, thanks.

    I know the kind of thing I try to protect my code against is very dirty.
    I try my best, I'll document everything else, indeed.

    Adrien.
    Adrien BARREAU, May 24, 2013
    #13
  14. Adrien BARREAU <> wrote:
    >On 05/24/2013 06:54 PM, Ben Morrow wrote:
    >> Quoth Adrien BARREAU<>:
    >>> Of course, but this is meant to run on some computer where adding new
    >>> CPAN files is not an option.
    >>> That's not my choice and I can't help it.

    >>
    >> So copy the code out of Try/Tiny.pm into your own script.
    >>

    >Once again, I agree about that idea, but I'm not allowed to do that either.


    Then take 4 days off at full pay, come back, and claim that during those
    4 days you developed that piece of code. Problem solved.

    jue
    Jürgen Exner, May 24, 2013
    #14
  15. On 5/24/2013 4:05 AM, Adrien BARREAU wrote:
    > Hello all.
    >
    >
    > I'm trying to write a little wrapper which properly handles a call with
    > a timeout.
    >
    > Since I'm on a 5.10.1, I take care of all eval{} pitfalls I know (more
    > or less take some parts of Try::Tiny ideas just to do a proper eval).
    >
    > Here is the thing I don't know how to deal with.
    >
    > # ---
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > sub sleep10
    > {
    > local $@;
    > sleep 10;
    > }
    >
    > {
    > eval {
    > local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    > alarm 2;
    > sleep10();

    alarm(0); # <--- to here
    > };
    >
    > # alarm 0; #----- move inside eval {};



    Just an aside but, if you're not using Try::Tiny, you should move the
    alarm inside the eval{} to remove another small race condition.

    --
    Charles DeRykus
    Charles DeRykus, May 25, 2013
    #15
  16. Adrien BARREAU

    Dr.Ruud Guest

    it hurts when I press here (was: Re: Signals and local $@)

    On 25/05/2013 07:05, Charles DeRykus wrote:
    > On 5/24/2013 4:05 AM, Adrien BARREAU wrote:


    >> #!/usr/bin/perl
    >>
    >> use strict;
    >> use warnings;
    >>
    >> sub sleep10
    >> {
    >> local $@;
    >> sleep 10;
    >> }
    >>
    >> {
    >> eval {
    >> local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    >> alarm 2;
    >> sleep10();

    > alarm(0); # <--- to here
    >> };
    >>
    >> # alarm 0; #----- move inside eval {};

    >
    >
    > Just an aside but, if you're not using Try::Tiny, you should move the
    > alarm inside the eval{} to remove another small race condition.


    It must be in both places, if you assume that sleep10 can die for
    multiple reasons.
    And the return-value of the eval{} must be checked, after forcing it to
    1 for success. Etc.

    --
    Ruud
    Dr.Ruud, May 25, 2013
    #16
  17. Re: it hurts when I press here

    On 5/25/2013 5:59 AM, Dr.Ruud wrote:
    > On 25/05/2013 07:05, Charles DeRykus wrote:
    >> On 5/24/2013 4:05 AM, Adrien BARREAU wrote:

    >
    >>> #!/usr/bin/perl
    >>>
    >>> use strict;
    >>> use warnings;
    >>>
    >>> sub sleep10
    >>> {
    >>> local $@;
    >>> sleep 10;
    >>> }
    >>>
    >>> {
    >>> eval {
    >>> local $SIG{'ALRM'} = sub { die "Here comes the death\n"; };
    >>> alarm 2;
    >>> sleep10();

    >> alarm(0); # <--- to here
    >>> };
    >>>
    >>> # alarm 0; #----- move inside eval {};

    >>
    >>
    >> Just an aside but, if you're not using Try::Tiny, you should move the
    >> alarm inside the eval{} to remove another small race condition.

    >
    > It must be in both places, if you assume that sleep10 can die for
    > multiple reasons.


    Yes, mea culpa. Of course sleep10 as shown didn't 'die' and wasn't
    re-throwing the exception... which threw me :)

    > And the return-value of the eval{} must be checked, after forcing it to
    > 1 for success. Etc.
    >


    And, even with that, it should be mentioned Try::Tiny is a better solution.

    --
    Charles DeRykus
    Charles DeRykus, May 25, 2013
    #17
  18. Re: it hurts when I press here

    Charles DeRykus <> writes:
    > On 5/25/2013 5:59 AM, Dr.Ruud wrote:


    [...]

    >> And the return-value of the eval{} must be checked, after forcing it to
    >> 1 for success. Etc.

    >
    > And, even with that, it should be mentioned Try::Tiny is a better
    > solution.


    In the sense that it has three times as much 'voodoo coding' but
    (hark!) nobody needs to look at the mess. Apart from that, these
    opinion statements regarding 'proper error handling' would be more
    convincing if they were expressed as opinion statements and came with
    a reason eg "I'm generally of the opinion that exceptions shouldn't be
    used for error handling because ...".

    I'm using eval and die extensively, both for aborting some sequence of
    processing steps from nested subroutines and for actual exception
    handling and this works very nicely. Some remarks about Try::Tiny:

    ,----
    | finally (&;$)
    |
    | [...]
    |
    | This allows you to locate cleanup code which cannot be
    | done via local() e.g. closing a file handle.
    `----

    This would be more aptly described as 'This construct is necessary to
    work around deficiencies of a sixty year old concept for "automatic
    memory management" which is limited to manageing memory while all
    other resources which need to be allocated and freed have to be
    managed with explicitly written code. That's not a problem for Perl 5
    which uses a more modern approach for automatic resource management
    with support for stack unwinding, deterministic finalization and
    automatic management of file handles *BUT* it will become a problem
    with Perl 6, should that ever evolve beyond being an abandoned Haskell
    demo."

    ,----
    | There are a number of issues with eval.
    `----

    ,----
    | Clobbering $@
    |
    | When you run an eval block and it succeeds, $@ will be cleared,
    | potentially clobbering an error that is currently being caught.
    `----

    That's an inherent limitation of the idea to use 'a global variable'
    as 'the exception location' and part of the documented functionlity of
    eval. The solution is that someone who wants to use $@ for exception
    handling has to save the value in some other location before starting
    any more complicated unrelated computation.

    ,----
    | Localizing $@ silently masks errors
    |
    | Inside an eval block, die behaves sort of like:
    |
    | sub die {
    | $@ = $_[0];
    | return_undef_from_eval();
    | }
    |
    | This means that if you were polite and localized $@ you can't die in
    | that scope, or your error will be discarded (printing "Something's
    | wrong" instead).
    `----

    'Localizing $@# does not 'silently mask errors', it localizes $@, that
    is, it creates a lexically scoped binding for a global
    variable. Because of this, changes to $@ while this binding is in
    scope will not affect 'the outside world' anyhow. Since $@ is used for
    exception propagation, this means that code which localizes $@ without
    dealing with this possibility 'might silently mask an error' aka 'is
    broken'.

    ,----
    | $@ might not be a true value
    |
    | This code is wrong:
    |
    | if ( $@ ) {
    | ...
    | }
    |
    | because due to the previous caveats it
    | may have been unset.
    `----

    This example is incomplete: The code supposed to set $@ is
    missing. Also, there were no general 'previous caveats': The first
    situation roughly amounts to the following:

    eval {
    ...;
    ...;
    }

    eval {
    ...;
    ...;
    }

    if ($@) {
    }

    plus the expectation that the value of $@ would reflect something
    which happened during the first eval which it doesn't: This is a
    coding error and needs to be avoided. Localizing $@ without dealing
    with its 'special magic' is also a coding error.

    ,----
    | The classic failure mode is:
    |
    | [...]
    |
    | In this case since Object::DESTROY is not localizing $@ but still uses
    | eval, it will set $@ to "".
    `----

    That's the sole valid concern so far: Object destructors are executed
    automatically during stack unwinding. Because of this, it is prudent
    to write them such that they don't modify any kind of 'state
    information' visible to unrelated parts of the program. That's the
    downside of any 'convenience mechanism' which might lead to the
    execution of subroutines in places where this isn't obvious when
    looking at the code causing these invocation. 'Operator overloading'
    suffers from the same problem. Not related to eval/ $@ in any
    particular way.

    NB: This text is an opinion statement itself and there might well be
    valid counterarguments for anything contained in it.
    Rainer Weikusat, May 25, 2013
    #18
  19. Re: it hurts when I press here

    On 5/25/2013 12:44 PM, Rainer Weikusat wrote:
    > Charles DeRykus <> writes:
    >> On 5/25/2013 5:59 AM, Dr.Ruud wrote:

    >
    > [...]
    >
    >>> And the return-value of the eval{} must be checked, after forcing it to
    >>> 1 for success. Etc.

    >>
    >> And, even with that, it should be mentioned Try::Tiny is a better
    >> solution.

    >
    > In the sense that it has three times as much 'voodoo coding' but
    > (hark!) nobody needs to look at the mess. Apart from that, these
    > opinion statements regarding 'proper error handling' would be more
    > convincing if they were expressed as opinion statements and came with
    > a reason eg "I'm generally of the opinion that exceptions shouldn't be
    > used for error handling because ...".
    >
    > I'm using eval and die extensively, both for aborting some sequence of
    > processing steps from nested subroutines and for actual exception
    > handling and this works very nicely.


    Good objection. Admittedly, I was mostly parroting the consensus about
    Try::Tiny. Still IMO most are better off with T::T than rolling an eval
    eval block. It's easy to forget the subtleties of Perl's exception
    handling... or remain blissfully unaware of them in the first place. For
    the latter reason, I can't comment in any depth.

    But, if 'sleep10' had been using T::T -- instead of mangling $@ as it
    apparently did and which is easy to do -- the code would have arguably
    been cleaner and chances of mayhem reduced. Even visually, I'd prefer:
    try{} catch {} rather than: local $@; eval{...;1};

    That's not a big edge but with eval, you have also to remember to
    localize $@ and to ensure the block returns true. Plus there can be
    concerns as you cite of a DESTROY block which zaps $@. IIUC, T:T handles
    these problems for you

    Both approaches involve discipline of course. Even with T::T, a global
    $_ is in play if errors occur. But, at least there's not the potential
    of collateral damage to the exception model itself because of $@
    vulnerability.


    --
    Charles DeRykus
    Charles DeRykus, May 26, 2013
    #19
  20. Re: it hurts when I press here

    Charles DeRykus <> writes:
    > On 5/25/2013 12:44 PM, Rainer Weikusat wrote:
    >> Charles DeRykus <> writes:
    >>> On 5/25/2013 5:59 AM, Dr.Ruud wrote:

    >>
    >> [...]
    >>
    >>>> And the return-value of the eval{} must be checked, after forcing it to
    >>>> 1 for success. Etc.
    >>>
    >>> And, even with that, it should be mentioned Try::Tiny is a better
    >>> solution.

    >>
    >> In the sense that it has three times as much 'voodoo coding' but
    >> (hark!) nobody needs to look at the mess. Apart from that, these
    >> opinion statements regarding 'proper error handling' would be more
    >> convincing if they were expressed as opinion statements and came with
    >> a reason eg "I'm generally of the opinion that exceptions shouldn't be
    >> used for error handling because ...".
    >>
    >> I'm using eval and die extensively, both for aborting some sequence of
    >> processing steps from nested subroutines and for actual exception
    >> handling and this works very nicely.

    >
    > Good objection. Admittedly, I was mostly parroting the consensus about
    > Try::Tiny.


    Consensus of whom? Obviously, all people who use Try::Tiny do so
    because they're convinced that it is useful for them. But this doesn't
    necessarily mean that it actually is. As someone wrote in a complete
    different context: Science is not a democracy because 'truth' is not
    'what most people believe in'.

    > Still IMO most are better off with T::T than rolling an
    > eval eval block. It's easy to forget the subtleties of Perl's
    > exception handling... or remain blissfully unaware of them in the
    > first place.


    The Try::Tiny documentation list three 'concerns' about 'Perl exception
    handling' (I consider two of them invalid for reasons stated
    elsewhere) but it contains no less than seven 'caveats' supposed to
    apply to using it (and some of the open bugs -- apparently, bugs in
    Try::Tiny are usually neither fixed nor closed -- are about people who
    still didn't understand how to use it). Memoizing more than two times
    as much 'subtleties' about using Try::Tiny in order to avoid learning
    about 'the subtleties of Perl exception handling' doesn't seem like a
    sensible tradeoff to me.

    Not to mention that most details of the Try::Tiny code are quoted (in
    simplified form) in the documentation and the author himself
    consistently refers to them as 'ugly hacks' (I agree with this
    assessment :->).

    > But, if 'sleep10' had been using T::T -- instead of mangling $@ as it
    > apparently did and which is easy to do -- the code would have arguably
    > been cleaner and chances of mayhem reduced. Even visually, I'd prefer:
    > try{} catch {} rather than: local $@; eval{...;1};


    And I prefer to use a facility for dealing with 'exceptional events'
    (which change the 'normally linear' control flow of something) for
    doing actual 'exception throwing and handling'. Otherwise, I'd use
    some 'special return value' error signalling convention without the
    overhead of the former. Mixing both in this way in order to work
    around hypothetical bugs in other code (instead of fixing these) is IMHO
    just totally bizarre: The point of having 'exceptions' in the first
    place is that return values can be used for returning 'useful
    information' and exceptions for 'exceptional events'.

    I also don't quite understand why one would localize $@ and want to
    propagate errors out of the scope of the local at the same time. The
    easy way to accomplish that would be not localizing $@ to begin with.
    Rainer Weikusat, May 26, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. karim
    Replies:
    1
    Views:
    752
    George Ter-Saakov
    Jun 26, 2003
  2. =?Utf-8?B?WVNVVA==?=

    Access local port or Running local exe file

    =?Utf-8?B?WVNVVA==?=, Jan 14, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    482
    =?Utf-8?B?WVNVVA==?=
    Jan 14, 2006
  3. Jim in Arizona
    Replies:
    8
    Views:
    4,952
    Jim in Arizona
    Jan 24, 2006
  4. lurker
    Replies:
    1
    Views:
    684
    Disco Octopus
    Apr 5, 2005
  5. andres
    Replies:
    1
    Views:
    5,227
    dgoyani
    Oct 23, 2007
Loading...

Share This Page