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

Re: Confused by eval behavior

Thread Previous | Thread Next
From:
perl
Date:
July 18, 2016 16:29
Subject:
Re: Confused by eval behavior
Message ID:
c3f8926e-d27f-0418-c25b-cd5638a72637@profvince.com
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.


Vincent

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