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. VincentThread Previous | Thread Next