List Info

Thread: (resent) Typeglobs vs. SUPER:: (Hook::LexWrap failure)




(resent) Typeglobs vs. SUPER:: (Hook::LexWrap failure)
user name
2007-10-07 12:03:56
# New Ticket Created by  Max Maischein 
# Please include the string:  [perl #46217]
# in the subject line of all future correspondence about
this issue. 
# <URL: h
ttp://rt.perl.org/rt3/Ticket/Display.html?id=46217 >


This is a bug report for perl from corioncpan.org,
generated with the help of perlbug 1.36 running under perl
5.10.0.

package main;
use strict;

=head1 DESCRIPTION

This test program shows a difference in behaviour
between 5.8.8 and 5.10. Under 5.8.8, the dynamic
wrapping of methods works and the wrapper always
gets called.

Under 5.10, the wrapper only gets called once.
If you remove the ->SUPER:: call at the end
of the test, it works under 5.10. Unfortunately,
removing elements from a class hierarchy is not
always possible.

=cut

use Test::More tests => 4;
use vars qw( %called );

for my $name (1..2) {
   %called = ();
   my lines = (1,2);
   my $requests = scalar lines;

   # Install the request dumper :
   my $unwind;
   { no warnings 'redefine';
     my $old_request = &Dummy::UserAgent::request;
     *Dummy::UserAgent::request = sub {
         goto &$old_request if $unwind;
         $called++;
         $old_request->(_);
     };
   };
   my $agent = Dummy::Mechanize->new();

   for my $line (lines) {
       $agent->get($line);
   };
   is($called,$requests,"$requests calls were
made to the 
wrapper for round $name");
   is($called,$requests,"$requests calls were
made in total for 
round $name");

   # Release the hook
   $unwind++;
};

sub Dummy::UserAgent::new { bless {}, shift };
sub Dummy::UserAgent::request { $main::called++ };

package Dummy::Mechanize;
use strict;
use vars 'ISA';
BEGIN { ISA = 'Dummy::UserAgent' };
sub get { my $s = shift; $s->request(_) };

# If you comment out this line, all is well:
sub request { my $s = shift; $s->SUPER::request(_) };
---
Flags:
     category=core
     severity=high
---
Site configuration information for perl 5.10.0:

Configured by corion at Sat Oct  6 20:19:19 CEST 2007.

Summary of my perl5 (revision 5 version 10 subversion 0
patch 32052) 
configuration:
   Platform:
     osname=linux, osvers=2.6.17-2-k7, archname=i686-linux
     uname='linux aliens 2.6.17-2-k7 #1 smp wed sep 13
17:18:46 utc 2006 
i686 gnulinux '
     config_args='-Dprefix=/opt/perl -des'
     hint=recommended, useposix=true, d_sigaction=define
     useithreads=undef, usemultiplicity=undef
     useperlio=define, d_sfio=undef, uselargefiles=define,
usesocks=undef
     use64bitint=undef, use64bitall=undef,
uselongdouble=undef
     usemymalloc=n, bincompat5005=undef
   Compiler:
     cc='cc', ccflags ='-fno-strict-aliasing -pipe
-I/usr/local/include 
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
     optimize='-O2',
     cppflags='-fno-strict-aliasing -pipe
-I/usr/local/include'
     ccversion='', gccversion='4.1.2 20061115 (prerelease)
(Debian 
4.1.1-21)', gccosandvers=''
     intsize=4, longsize=4, ptrsize=4, doublesize=8,
byteorder=1234
     d_longlong=define, longlongsize=8, d_longdbl=define,
longdblsize=12
     ivtype='long', ivsize=4, nvtype='double', nvsize=8,
Off_t='off_t', 
lseeksize=8
     alignbytes=4, prototype=define
   Linker and Libraries:
     ld='cc', ldflags =' -L/usr/local/lib'
     libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
     libs=-lnsl -ldl -lm -lcrypt -lutil -lc
     perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
     libc=/lib/libc-2.3.6.so, so=so, useshrplib=false,
libperl=libperl.a
     gnulibc_version='2.3.6'
   Dynamic Linking:
     dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef,
ccdlflags='-Wl,-E'
     cccdlflags='-fPIC', lddlflags='-shared -O2
-L/usr/local/lib'

Locally applied patches:
     DEVEL

---
INC
for perl 5.10.0:
     /opt/perl/lib/5.10.0/i686-linux
     /opt/perl/lib/5.10.0
     /opt/perl/lib/site_perl/5.10.0/i686-linux
     /opt/perl/lib/site_perl/5.10.0
     /opt/perl/lib/site_perl/5.8.8
     /opt/perl/lib/site_perl/5.8.7
     /opt/perl/lib/site_perl
     .

---
Environment for perl 5.10.0:
     HOME=/home/corion
     LANG=de_DE.UTF-8
     LANGUAGE (unset)
     LD_LIBRARY_PATH (unset)
     LOGDIR (unset)
 
PATH=/home/corion/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/
X11:/usr/games:/home/corion/bin:/home/corion/bin
     PERL_BADLANG (unset)
     SHELL=/bin/bash


Re: (resent) Typeglobs vs. SUPER:: (Hook::LexWrap failure)
user name
2007-10-07 22:36:36
On 10/7/07, via RT Max Maischein <perlbug-followupperl.org> wrote:
> This test program shows a difference in behaviour
> between 5.8.8 and 5.10. Under 5.8.8, the dynamic
> wrapping of methods works and the wrapper always
> gets called.
>
> Under 5.10, the wrapper only gets called once.
> If you remove the ->SUPER:: call at the end
> of the test, it works under 5.10. Unfortunately,
> removing elements from a class hierarchy is not
> always possible.

I think you've found a buggy interaction between SUPER and
the new
method caching code.

Recap of SUPER (skip this if you know how it works):  When
code
invokes a SUPER method (for example, via
"Foo->SUPER::bar()",
"Foo::SUPER::bar()", or
"$foo_obj->SUPER::bar()"),
gv_fetchmethod_autoload autovivifies an empty package
"Foo::SUPER" if
one didn't already exist, and then asks gv_fetchmeth() to
resolve the
bar method there.  gv_fetchmeth() will return cache entries
from this
special package if they exist.  Otherwise it looks up the
method in
the parents of Foo (ignoring Foo itself), and caches
whatever it finds
in the special SUPER package for later cache re-use.

The problem is that the special SUPER package isn't tied
into the new
method cache management stuff (mro cache_gen, magical ISA
change
triggers, etc).  Cache entries are being created in the
SUPER
packages, but they aren't being properly invalidated at the
right
times.

There are a few different ways to go about fixing this. 
This simplest
and most foolproof way would simply be to disable caching
SUPER
lookups, but I doubt anyone wants that answer.  The most
correct
solution is probably to revamp how SUPER lookups work in
general, and
use ISA aliasing (which doesn't yet working right
anyways).

I've attached a patch for what I think is a reasonable
compromise
approach.  In this patch, when the Foo::SUPER stash is
autovivified, a
new Foo::SUPER::ISA (with magic) which contains just one
entry for
"Foo" is created.  Because of the way SUPER is
specially handled in
the fetchmeth functions, this ISA won't actually get used
for
lookups, but it serves to tie FOO::SUPER into the cache
management
code in the right way such that its caches are invalidated
at the
right times.  It also makes the test case in this ticket
pass.

What do you guys think?

-- Brandon

  
[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )