Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.perl.misc > #4636

Re: $var = do { ... }?

From Rainer Weikusat <rweikusat@mssgmbh.com>
Newsgroups comp.lang.perl.misc
Subject Re: $var = do { ... }?
Date 2012-03-05 20:50 +0000
Message-ID <87d38qai2v.fsf@sapphire.mobileactivedefense.com> (permalink)
References (1 earlier) <v4o929-1u.ln1@news.rtij.nl> <87ipil1ueb.fsf@sapphire.mobileactivedefense.com> <q8ka29-733.ln1@news.rtij.nl> <0kpa29-lke2.ln1@anubis.morrow.me.uk> <87eht81l47.fsf@sapphire.mobileactivedefense.com>

Show all headers | View raw


Rainer Weikusat <rweikusat@mssgmbh.com> writes:
> Ben Morrow <ben@morrow.me.uk> writes:

[...]


>> Localising $@ in DESTROY would not be sufficient, even if you could rely

[...]

>> See the BACKGROUND section of Try::Tiny's documentation.
>
> Hic Rhodos, hic salta: What are you precisely referring to? I read
> this background section and wrote about the two things I found in
> there which were not just handwaiving. So, what did I miss and/or get
> wrong?

Since (somewhat expectedly) nothing came of that and I've re-read the
Try::Tiny BACKGROUND section meanwhile with more attention to detail,
I now confidently state that the 'Localizing ... would not be
sufficient' statement is wrong. Adressing each of the 'rationales' in
turn:

,----
| Clobbering $@
|
| When you run an eval block and it succeeds, $@ will be
| cleared, potentially clobbering an error that is currently
| being caught.
| 
| [...]
| 
| $@ must be properly localized before invoking eval in order to avoid
| this issue.
`----

As I already wrote: This is the documented behaviour of eval and it is
the responsibility of the code which is interested in the content of
$@ to store that in some safe place before invoking other code which
might cause the value of $@ to be changed. That's a side effect of the
design descision to use a global variable to store the most recently
thrown exception. Taking this into account, this design descision can
certainly be called 'somewhat unfortunate', however, this is argueing
about spilt milk: perl behaves in the way it does and application
code written in Perl needs to take this into account. It is in no way
sensible to burden code which is regularly executed with working
around possible errors in the calling code, as suggested in the '$@
must be properly localized'.

,----
| 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).
`----

... not only is the idea to always localize $@ 'just in case' before
executing eval not sensible, it additionally breaks exception
propagation out of the current lexical scope. But since it is only
necessary to work around this problematic side effect when proactively
trying to work around the non-problem described in the previous
paragraph, this is not generally an issue.

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

But there were no such 'previous caveats', just a remark about the
documented behaviour of eval and how that may interact badly with some
calling code written based on the wrong assumption that $@ would not
be a global variable. Actually, $@ can't be 'unset' except as side
effect of code which runs between the time of the original die and the
time the caller looks at $@. Minus the already mentioned 'caller bug'
of not saving $@, this leaves a single possible problem situation,
namely,

,----
| The classic failure mode is:
| 
|         sub Object::DESTROY {
|                 eval { ... }
|         }
| 
|         eval {
|                 my $obj = Object->new;
| 
|                 die "foo";
|         };
| 
|         if ( $@ ) {
| 
|         }
`----

This is an actual problem because destructors can be executed after a
die and before the caller of the eval ever gets a chance to look at
$@. As I already wrote, because of this, a destructor which doesn't
localize $@ if it already has a value before executing code which
might either eval or die is broken. It is possible that the value in
$@ isn't interesting to the (indirect) caller anymore and that the
destructor just sees it because $@ is a global variable, but there's
no way to distinguish between these two cases.

Lastly,

,----
| The workaround for this is even uglier than the previous ones. Even
| though we can't save the value of $@ from code that doesn't localize,
| we can at least be sure the eval was aborted due to an error:
| 
| 
|         my $failed = not eval {
|                 ...
| 
|                 return 1;
|         };
`----

there's little point in disabling useful features (out-of-band error
signalling, eval return values) in order to work around hypothetical
bugs in destructors. Instead, the buggy destructors need to be fixed.

Back to comp.lang.perl.misc | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

$var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-02 17:15 +0000
  Re: $var = do { ... }? merlyn@stonehenge.com (Randal L. Schwartz) - 2012-03-02 09:52 -0800
  Re: $var = do { ... }? Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> - 2012-03-02 13:42 -0500
  Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-02 18:44 +0000
    Re: $var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-02 19:00 +0000
      Re: $var = do { ... }? merlyn@stonehenge.com (Randal L. Schwartz) - 2012-03-02 11:45 -0800
      Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-02 20:06 +0000
  Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-02 19:18 +0000
    Re: $var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-02 19:24 +0000
      Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-02 20:10 +0000
        Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-02 20:43 +0000
          Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-02 22:47 +0000
          Re: $var = do { ... }? Martijn Lievaart <m@rtij.nl.invlalid> - 2012-03-03 15:58 +0100
            Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-03 17:11 +0000
              Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-03 17:19 +0000
              Re: $var = do { ... }? Martijn Lievaart <m@rtij.nl.invlalid> - 2012-03-03 23:58 +0100
                Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-04 00:29 +0000
                Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-04 14:44 +0000
                Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-05 20:50 +0000
        Re: $var = do { ... }? "Dr.Ruud" <rvtol+usenet@xs4all.nl> - 2012-03-05 11:35 +0100
          Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-05 15:22 +0000
          Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-05 16:38 +0000
      Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-02 20:44 +0000
  Re: $var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-15 17:09 +0000
    Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-16 00:18 +0000
      Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-16 14:25 +0000
        Re: $var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-16 21:01 +0000
          Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-16 21:37 +0000
          Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-16 22:56 +0000
            Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-16 23:54 +0000
            Re: $var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-17 18:48 +0000
              Re: $var = do { ... }? Ben Morrow <ben@morrow.me.uk> - 2012-03-17 22:53 +0000
              Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-18 15:40 +0000
    Re: $var = do { ... }? "Dr.Ruud" <rvtol+usenet@xs4all.nl> - 2012-03-16 14:08 +0100
      Re: $var = do { ... }? tmcd@panix.com (Tim McDaniel) - 2012-03-16 15:25 +0000
      Re: $var = do { ... }? Rainer Weikusat <rweikusat@mssgmbh.com> - 2012-03-16 17:46 +0000

csiph-web