Skip Menu |
 
Report information
Id: 105024
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: mauke- <l.mai [at] web.de>
Cc:
AdminCc:

Operating System: Linux
PatchStatus: (no value)
Severity: low
Type: core
Perl Version: 5.12.3
Fixed In: (no value)



Subject: UNIVERSAL::AUTOLOAD breaks named captures/%-/%+
Date: Wed, 30 Nov 2011 22:39:28 +0100
To: perlbug [...] perl.org
From: l.mai [...] web.de
Download (untitled) / with headers
text/plain 4.5k
This is a bug report for perl from l.mai@web.de, generated with the help of perlbug 1.39 running under perl 5.12.3. ----------------------------------------------------------------- [Please describe your issue here] % perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. Use of uninitialized value $+{"X"} in string at -e line 1. % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. a Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8)) at -e line 1 during global destruction. Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global destruction. So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+, even if AUTOLOAD is never called. But (for some reason) letting the parser see %+ early makes things work as expected. As far as I can tell this is broken in 5.12 and 5.10 but works in 5.14, probably because Tie::Hash::NamedCapture is a real (XS) module there. Any idea what's going on? [Please do not change anything below this line] ----------------------------------------------------------------- --- Flags: category=core severity=low --- Site configuration information for perl 5.12.3: Configured by mauke at Tue Aug 9 13:00:53 CEST 2011. Summary of my perl5 (revision 5 version 12 subversion 3) configuration: Platform: osname=linux, osvers=2.6.37-gentoo-r4, archname=i686-linux uname='linux nora 2.6.37-gentoo-r4 #5 preempt sun may 8 03:58:55 cest 2011 i686 amd athlon(tm) 64 processor 3200+ authenticamd gnulinux ' config_args='-de -Dprefix=/home/mauke/usr/perlbrew/perls/perl-5.12.3' 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 -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.4.5', 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 =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc libc=/lib/libc-2.12.2.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.12.2' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector' Locally applied patches: --- @INC for perl 5.12.3: /home/mauke/usr/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/i686-linux /home/mauke/usr/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3 /home/mauke/usr/perlbrew/perls/perl-5.12.3/lib/5.12.3/i686-linux /home/mauke/usr/perlbrew/perls/perl-5.12.3/lib/5.12.3 . --- Environment for perl 5.12.3: HOME=/home/mauke LANG=en_US.UTF-8 LANGUAGE (unset) LC_COLLATE=POSIX LD_LIBRARY_PATH=/home/mauke/usr/local/lib LOGDIR (unset) PATH=/home/mauke/usr/perlbrew/bin:/home/mauke/usr/perlbrew/perls/perl-5.12.3/bin:/home/mauke/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/i686-pc-linux-gnu/gcc-bin/4.4.5:/opt/sun-jdk-1.4.2.13/bin:/opt/sun-jdk-1.4.2.13/jre/bin:/opt/sun-jdk-1.4.2.13/jre/javaws:/opt/dmd/bin:/usr/games/bin PERLBREW_HOME=/home/mauke/.perlbrew PERLBREW_PATH=/home/mauke/usr/perlbrew/bin:/home/mauke/usr/perlbrew/perls/perl-5.12.3/bin PERLBREW_PERL=perl-5.12.3 PERLBREW_ROOT=/home/mauke/usr/perlbrew PERLBREW_VERSION=0.27 PERL_BADLANG (unset) PERL_UNICODE=SAL SHELL=/bin/bash
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.3k
Additional data points ... This is what I got on Linux for first 5.12.0, then 5.14.2: ### $ /usr/local/bin/perl5.12.0 -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x817adf8)) at -e line 1. Use of uninitialized value $+{"X"} in string at -e line 1. ### $ perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' version::DESTROY(v5.14.0) at -e line 1. version::DESTROY(v5.14.0) at -e line 1. version::DESTROY(v5.14.0) at -e line 1. version::DESTROY(0.08) at -e line 1. version::DESTROY(0.08) at -e line 1. version::DESTROY(v5.14.0) at -e line 1. IO::File::DESTROY(IO::File=IO(0x8189ff0)) at -e line 1. a Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x8196b68)) at -e line 1 during global destruction. Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x8196bd8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x8189e10)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x817ada8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x817ade8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x817ae28)) at -e line 1 during global destruction. ### Similar results with these two Perl versions on Darwin.
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.7k
On Wed Nov 30 13:39:47 2011, l.mai@web.de wrote: Show quoted text
> % perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" > } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' > IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. > Use of uninitialized value $+{"X"} in string at -e line 1. > > % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn > "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' > IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. > a >
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8)) Show quoted text
> at -e line 1 during global destruction. >
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8)) Show quoted text
> at -e line 1 during global destruction. > IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global > destruction. > IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global > destruction. > IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global > destruction. > > > So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+, > even if > AUTOLOAD is never called. But (for some reason) letting the parser see > %+ early > makes things work as expected. > > As far as I can tell this is broken in 5.12 and 5.10 but works in > 5.14, > probably because Tie::Hash::NamedCapture is a real (XS) module there. > > Any idea what's going on?
It was indeed this commit that made the difference, but I cannot understand why: commit 8dcfe2e99a72fe7951b4d15325e1541232823204 Author: Nicholas Clark <nick@ccl4.org> Date: Thu Oct 14 15:34:03 2010 +0100 Move remaining Tie::Hash::NamedCapture XS code to NamedCapture.xs Now all the support code for %+ and %- is contained in the module in ext/ -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 3.1k
On Wed Nov 30 17:49:48 2011, sprout wrote: Show quoted text
> On Wed Nov 30 13:39:47 2011, l.mai@web.de wrote:
> > % perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" > > } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' > > IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. > > Use of uninitialized value $+{"X"} in string at -e line 1. > > > > % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn > > "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' > > IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. > > a > >
>
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8)) Show quoted text
> > at -e line 1 during global destruction. > >
>
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8)) Show quoted text
> > at -e line 1 during global destruction. > > IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global > > destruction. > > IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global > > destruction. > > IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global > > destruction. > > > > > > So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+, > > even if > > AUTOLOAD is never called. But (for some reason) letting the parser see > > %+ early > > makes things work as expected. > > > > As far as I can tell this is broken in 5.12 and 5.10 but works in > > 5.14, > > probably because Tie::Hash::NamedCapture is a real (XS) module there. > > > > Any idea what's going on?
> > It was indeed this commit that made the difference, but I cannot > understand why: > > commit 8dcfe2e99a72fe7951b4d15325e1541232823204 > Author: Nicholas Clark <nick@ccl4.org> > Date: Thu Oct 14 15:34:03 2010 +0100 > > Move remaining Tie::Hash::NamedCapture XS code to NamedCapture.xs > > Now all the support code for %+ and %- is contained in the module in > ext/ >
I’ve just figured it out. In gv.c: S_require_tie_mod(pTHX_ GV *gv, const char *varpv, SV* namesv, const char *methpv,const U32 flags) { dVAR; HV* stash = gv_stashsv(namesv, 0); PERL_ARGS_ASSERT_REQUIRE_TIE_MOD; if (!stash || !(gv_fetchmethod(stash, methpv))) { In gv.h: #define gv_fetchmethod(stash, name) gv_fetchmethod_autoload(stash, name, TRUE) So, if either the stash does not exist (as in 5.14; in 5.12 parts of it are in core), or the method (TIEHASH in this case) cannot be found, even by autoloading, then the module is loaded. That means the problem still persists in 5.14. You just have to mention the package (e.g., ‘Tie::Hash::NamedCapture::Googoo() if 0’) and the presence of a universal autoload sub will stop (compilation of) %- and %+ from loading the module. S_require_tie_mod probably should not be autoloading. Errno and arybase have the same problem: $ ./perl -Ilib -le 'arybase::Googoo() if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } $[ = 1; print qw(a b c)[2]' IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1. c (should print b) $ ./perl -Ilib -le 'Errno::onrrE() if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } $!=20; print $!{ENOTDIR}' IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1. (should print 20, on Unix at least) -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 3.5k
On Wed Nov 30 18:04:50 2011, sprout wrote: Show quoted text
> On Wed Nov 30 17:49:48 2011, sprout wrote:
> > On Wed Nov 30 13:39:47 2011, l.mai@web.de wrote:
> > > % perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" > > > } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' > > > IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. > > > Use of uninitialized value $+{"X"} in string at -e line 1. > > > > > > % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn > > > "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"' > > > IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. > > > a > > >
> >
>
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8)) Show quoted text
> > > at -e line 1 during global destruction. > > >
> >
>
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8)) Show quoted text
> > > at -e line 1 during global destruction. > > > IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global > > > destruction. > > > IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global > > > destruction. > > > IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global > > > destruction. > > > > > > > > > So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+, > > > even if > > > AUTOLOAD is never called. But (for some reason) letting the parser see > > > %+ early > > > makes things work as expected. > > > > > > As far as I can tell this is broken in 5.12 and 5.10 but works in > > > 5.14, > > > probably because Tie::Hash::NamedCapture is a real (XS) module there. > > > > > > Any idea what's going on?
> > > > It was indeed this commit that made the difference, but I cannot > > understand why: > > > > commit 8dcfe2e99a72fe7951b4d15325e1541232823204 > > Author: Nicholas Clark <nick@ccl4.org> > > Date: Thu Oct 14 15:34:03 2010 +0100 > > > > Move remaining Tie::Hash::NamedCapture XS code to NamedCapture.xs > > > > Now all the support code for %+ and %- is contained in the module in > > ext/ > >
> > I’ve just figured it out. In gv.c: > > S_require_tie_mod(pTHX_ GV *gv, const char *varpv, SV* namesv, const > char *methpv,const U32 flags) > { > dVAR; > HV* stash = gv_stashsv(namesv, 0); > > PERL_ARGS_ASSERT_REQUIRE_TIE_MOD; > > if (!stash || !(gv_fetchmethod(stash, methpv))) { > > In gv.h: > > #define gv_fetchmethod(stash, name) gv_fetchmethod_autoload(stash, name, > TRUE) > > So, if either the stash does not exist (as in 5.14; in 5.12 parts of it > are in core), or the method (TIEHASH in this case) cannot be found, even > by autoloading, then the module is loaded. > > That means the problem still persists in 5.14. You just have to mention > the package (e.g., ‘Tie::Hash::NamedCapture::Googoo() if 0’) and the > presence of a universal autoload sub will stop (compilation of) %- and > %+ from loading the module. > > S_require_tie_mod probably should not be autoloading. > > Errno and arybase have the same problem: > > $ ./perl -Ilib -le 'arybase::Googoo() if 0; { package UNIVERSAL; sub > AUTOLOAD { warn "$AUTOLOAD(@_)" } } $[ = 1; print qw(a b c)[2]' > IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1. > c > > (should print b) > > $ ./perl -Ilib -le 'Errno::onrrE() if 0; { package UNIVERSAL; sub > AUTOLOAD { warn "$AUTOLOAD(@_)" } } $!=20; print $!{ENOTDIR}' > IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1. > > (should print 20, on Unix at least) >
Now fixed with commit 0ea03996e. I hope my responses have given you enough information to pick the workaround of your choice. Now, back to tending the COWs.... -- Father Chrysostomos


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org