develooper Front page | perl.perl5.porters | Postings from August 2016

Re: Confused by eval behavior

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
August 22, 2016 16:37
Subject:
Re: Confused by eval behavior
Message ID:
20160822163716.GR3173@iabyn.com
On Mon, Jul 18, 2016 at 01:29:19PM -0300, Vincent Pit (VPIT) wrote:
> Le 18/07/2016 à 12:37, Dave Mitchell a écrit :
> > > The failing Variable::Magic test can be reduced to:
> > > 
> > >     use Variable::Magic qw<wizard cast>;
> > > 
> > >     my $wiz2 = wizard;
> > >     my $wiz1 = wizard free => sub { warn "recasting\n"; &cast($_[0], $wiz2); die; };
> > > 
> > >     eval {
> > >      my $v = do { my $val = 123; \$val };
> > >      &cast($v, $wiz1);
> > >     };
> > > 
> > > When $v goes out scope, the free magic method is called, which attached
> > > new magic then dies. vmg_call_sv catches the error, then croaks.
> > > The croak calls die_unwind, which now does FREETMPS, which triggers
> > > another call to the free method, and so it recurses infinitely.
> > > 
> > > I haven't looked closely to see what is being freed by the FREETMPS and
> > > why.
> > 
> > Vincent, will you have any opportunity to look at this?
> > 
> 
> I looked at it but I have no definite answer about how to solve it.
> 
> The part of the code that goes into infinite recursion is there to ensure
> that the Variable::Magic objects survive long enough that it is possible to
> still manipulate magic during free callbacks (note that in particular magic
> vtables have to be handled with extra care because they are shared across
> threads). In order to work around the issue covered by this very "Confused
> by eval behaviour" bug, the case where the free callback is invoked at the
> end of an eval scope is treated specifically in vmg_svt_free_cleanup() (in
> the branch where ud->in_eval is true). Then it uses different strategies
> (trampoline op, destructor added to $@) to delay magic cleanup after eval is
> done. Prior to your change, ud->in_eval was true in your example, but now
> it's false. I guess that the heuristic used to see if the destruction
> happens at the eval boundary has to be adjusted. I reckon that all this
> stuff is pretty hacky and brittle, but it used to work well enough that
> nobody complained.
> 
> As a data point, note that if you change the eval part of your test case by
> 
>   eval {
>     my $v = 123;
>     cast($v, $wiz1);
>   };
> 
> then the infinite recursion disappears but the free magic is called twice.

Well, in an ideal world with a perfect perl and a perfect V::M,
what is the  code at the top of this email supposed to do? In particular:

At the point where die is about to be called, is the magic var supposed
to have both wizards still attached, or just wiz2? (Or with both attached,
but $wiz1 in some way deactivated?).

And when exactly is the magic var supposed to be freed for the second
time (after having been temporarily resurrected by the free magic
creating a mortal reference to it)?

And is it intended that the free anon sub should called exactly once?

-- 
Any [programming] language that doesn't occasionally surprise the
novice will pay for it by continually surprising the expert.
   -- Larry Wall

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About