On Mon, Nov 19, 2001 at 09:48:41PM +0000, Matt wrote:
> my ( $x, $y ) = ( 500, 200 );
> 
> ...works. But:
> 
> use vars qw( $x $y );
> 
> ...does not. Similarly, if I neither 'my' them, or 'use vars qw' then it
> also crashes.

I can confirm that it fails on my machine, too.  It's very odd. 

I took a simple example like the above and looked at the Perl code 
generated.  Whittling it down to a really simple example, the following
are all roughly equivalent:

# straight reference to Perl sub

my $broken1 = sub {
    my $output  = '';
    
    eval { BLOCK: {
            $output .=  do {
                my $perl ='
                use vars qw( $x $y );
                $x = 10;
                ';
                    
                eval $perl;
            };
    } };
    if ($@) {
        die $@;
    }

    return $output;
};

# eval string to create reference (like the parser does)

my $broken2 = eval <<'EOF';
sub {
    my $output  = '';
    
    eval { BLOCK: {
            $output .=  do {
                my $perl ='
                use vars qw( $x $y );
                $x = 10;
                ';
                    
                eval $perl;
            };
    } };
    if ($@) {
        die $@;
    }

    return $output;
}
EOF

# define template to generate code like the above

my $broken3 =<<'EOF';
[% RAWPERL %]
            $output .=  do {
                my $perl ='
                use vars qw( $x $y );
                $x = 10;
                ';
                    
                eval $perl;
            };
[% END %]
EOF

# set them up as templates and run them

my $tt2 = Template->new( {
    EVAL_PERL => 1,
    BLOCKS    => { 
            broken1 => $broken1,
            broken2 => $broken2,
            broken3 => $broken3,
    },
} );

foreach my $n (1..3) {
    $tt2->process("broken$n")
        || die $tt2->error();
    
    print "\nbroken$n finished\n";
}


The result is that broken1 and broken2 run fine, but broken3 barfs with a
segfault.  It's weird because the parser that compiles broken3 is doing 
pretty much the same thing that broken2 is doing, constructing a string 
of perl code and running 'eval' on it to generate a sub ref.  However,
when we do just that it works fine, when we pass it over to the parser
to do it, it somehow constructs a truly broken subref which barfs when
run.

So then I try it on Perl 5.6.0 and it all works fine.  Broken on 5.6.1,
working on 5.6.0.  Broken on 5.6.1, working on 5.6.0.

[ pauses to compiled perl 5.7.2 ]

Hey!  It works on 5.7.2!  That's probably a good sign.

Looking at the Changes file for 5.7.2, this might be what we're looking
for:

____________________________________________________________________________
[  9584] By: gsar                                  on 2001/04/06  04:09:00
        Log: keep eval"" CVs alive until the end of the statement in which
             they're called; this avoids a coredump ensuing from search for
             lexicals in code such as:

             sub bug {
             my $s = @_;
             eval q[sub { eval 'sub { &$s }' }];
             }
             bug("x")->()->();

             this code still doesn't work as intended (as it has remained
             since time immemorial), but it doesn't provoke a coredump anymore
     Branch: maint-5.6/perl
           ! embed.h embed.pl global.sym objXSUB.h perlapi.c
           ! pod/perlguts.pod pp_ctl.c proto.h scope.c scope.h sv.c


That's the only reference I can find to "eval" which mentions dumping 
core, but there are plenty of other references to eval fixes in that
file.

Hopefully this means that the problem is now fixed, or at least is fixed
in the devel release of Perl which will eventually become the next stable
release.

Until then, I guess you could revert to 5.6.0, upgrade to 5.7.2 or follow
the old advice: 

  "Doctor Templates, my template crashes when I do [% this %]"
  "Well, don't do [% that %] then!"  

:-)

Hmm, need more coffee...

HTH
A





Reply via email to