Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.86k stars 528 forks source link

Constants with undef value deliver arbitrary value at first call #8379

Closed p5pRT closed 18 years ago

p5pRT commented 18 years ago

Migrated from rt.perl.org#38783 (status was 'resolved')

Searchable as RT38783$

p5pRT commented 18 years ago

From Markus.Herber@eds.com

Created by EADUnixServerAdmin@eds.com

Hi\,

I'm installing perl on an x86 Solaris 10 machine using gcc 3.4.6 and found a strange behaviour which I think is a bug in perl 5.8.x​:

Constants defined via XS are not as constant as expected for the perl 5.8.x series. I found following bug with 5.8.8\, 5.8.7\, and 5.8.2\, but not with 5.6.1 and 5.6.2\, (except for 5.6.1 all with gcc 3.4.6) when installing IO​::Tty version 1.02​:

perl Makefile.PL => OK make => OK make test => spits out a warning\, though reporting all tests OK

The warning is​:

... Use of uninitialized value in ioctl at /local/root/build/perl/addons/tmp/IO-Tty-1.02/blib/lib/IO/Pty.pm line 127. warning​: TIOCSCTTY failed\, slave might not be set as controlling terminal​: Invalid argument at /local/root/build/perl/addons/tmp/IO-Tty-1.02/blib/lib/IO/Pty.pm line 128. ok 2 ...

Actually this warning should be impossible as TIOCSCTTY should be a constant​:   if (defined TIOCSCTTY) {   if (not defined ioctl( ${*$self}{'io_pty_slave'}\, TIOCSCTTY\, 0 )) {   warn "warning​: TIOCSCTTY failed\, slave might not be set as controlling terminal​: $!" if $^W;   }   } elsif (defined TCSETCTTY) {   if (not defined ioctl( ${*$self}{'io_pty_slave'}\, TCSETCTTY\, 0 )) {   warn "warning​: TCSETCTTY failed\, slave might not be set as controlling terminal​: $!" if $^W;   }   }

I put following code in front of the first if(...) it and found out\, that when TIOCSCTTY called first time it returns the string which is argument to the next following warn()​:

use Data​::Dumper; print STDERR Dumper TIOCSCTTY; print STDERR Dumper TIOCSCTTY;

I got following output (and the warning vanished)​:

... $VAR1 = 'Error​: could not connect pty as controlling terminal! '; $VAR1 = undef; ok 2 ...

If I replace the first if(...) by if(0) I get a similar warning for TCSETCTTY from the elsif() part. This constant should also be undef. Thus the effect is not limited to one constant.

I found their definition in xssubs.c after 'perl Makefile.PL'​: ... newCONSTSUB(stash\, "TCSETCTTY"\, &PL_sv_undef); ... newCONSTSUB(stash\, "TIOCSCTTY"\, &PL_sv_undef); ...

Unfortunately I have no deeper insight in perl internals to efficiently debug this further.

I experienced also a lot of errors when testing Tk (only 27% success); I currently assume that this may be related\, but I have not had a closer look at the Tk problems\, as Tk is much more complex...

Best Regards\, Markus Herber.

Perl Info ``` Flags: category=core severity=high Site configuration information for perl v5.8.8: Configured by root at Thu Mar 16 18:35:29 CET 2006. Summary of my perl5 (revision 5 version 8 subversion 8) configuration: Platform: osname=solaris, osvers=2.10, archname=i86pc-solaris-thread-multi uname='sunos eadw01 5.10 generic_118844-26 i86pc i386 i86pc ' config_args='' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags ='-I/opt/perl-5.8.8/include -D_REENTRANT -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV -DPERL_USE_SAFE_PUTENV', optimize='-O', cppflags='-D_REENTRANT -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include' ccversion='', gccversion='3.4.6', gccosandvers='solaris2.10' 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='gcc', ldflags =' -L/usr/local/lib ' libpth=/opt/perl-5.8.8/lib /usr/local/lib /usr/lib /usr/ccs/lib libs=-lsocket -lnsl -ldl -lm -lpthread -lc perllibs=-lsocket -lnsl -ldl -lm -lpthread -lc libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-fPIC', lddlflags='-G -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.8: /opt/perl-5.8.8/lib/5.8.8/i86pc-solaris-thread-multi /opt/perl-5.8.8/lib/5.8.8 /opt/perl-5.8.8/lib/site_perl/5.8.8/i86pc-solaris-thread-multi /opt/perl-5.8.8/lib/site_perl/5.8.8 /opt/perl-5.8.8/lib/site_perl . Environment for perl v5.8.8: HOME=/local/root LANG=C LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/opt/perl-5.8.8/bin:/opt/perl-5.8.8/bin:/opt/gcc/bin:/local/scripts:/local/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/openwin/bin:/usr/bin:/bin:/usr/ucb:/usr/opt/SUNWmd/sbin:/usr/ccs/bin:/usr/dt/bin:/opt/SUNWhadf/bin:/opt/SUNWcluster/bin:/opt/SUNWvxva/bin:/opt/SUNWvxvm/bin:/opt/VRTSvxvm/bin:/opt/VRTSvmsa/bin:/opt/VRTSfsdoc/bin:/opt/SUNWsymon/sbin:/opt/SUNWsymon/bin:/opt/SUNWvmsa/bin:/usr/cluster/bin:/usr/bin/nsr:/opt/WLtop/bin:/opt/SUNWpnm/bin:/opt/SUNWexplo/bin:/opt/EMCpower/bin:/opt/Navisphere/bin:/opt/EMCse/bin PERL_BADLANG (unset) SHELL=/bin/ksh ```
p5pRT commented 18 years ago

From @nwc10

On Wed\, Mar 22\, 2006 at 03​:08​:49AM -0800\, Markus. Herber @​ eds. com wrote​:

I'm installing perl on an x86 Solaris 10 machine using gcc 3.4.6 and found a strange behaviour which I think is a bug in perl 5.8.x​:

Constants defined via XS are not as constant as expected for the perl 5.8.x series. I found following bug with 5.8.8\, 5.8.7\, and 5.8.2\, but not with 5.6.1 and 5.6.2\, (except for 5.6.1 all with gcc 3.4.6) when installing IO​::Tty version 1.02​:

I put following code in front of the first if(...) it and found out\, that when TIOCSCTTY called first time it returns the string which is argument to the next following warn()​:

use Data​::Dumper; print STDERR Dumper TIOCSCTTY; print STDERR Dumper TIOCSCTTY;

I got following output (and the warning vanished)​:

... $VAR1 = 'Error​: could not connect pty as controlling terminal! '; $VAR1 = undef; ok 2 ...

If I replace the first if(...) by if(0) I get a similar warning for TCSETCTTY from the elsif() part. This constant should also be undef. Thus the effect is not limited to one constant.

I found their definition in xssubs.c after 'perl Makefile.PL'​: ... newCONSTSUB(stash\, "TCSETCTTY"\, &PL_sv_undef); ... newCONSTSUB(stash\, "TIOCSCTTY"\, &PL_sv_undef); ...

Unfortunately I have no deeper insight in perl internals to efficiently debug this further.

Thanks for this bug report and an excellent description of how things seem to be going wrong.

I can't recreate this on FreeBSD with threads\, but I think I know what the problem is. I think it's something I hit upon before Christmas while working on improving how constants are stored. Whilst it bit me with my changes\, I didn't think that it was important with existing code\, as there was no way of triggering it with C\. I'd not thought of XS modules using newCONSTSUB with &PL_sv_undef.

I think that the appended patch will solve the bug. The problem arises when PL_sv_undef ends up being stored as a constant in a pad. It seems to be that the pad code thinks that this pad slot is free\, because the array code treats a pointer to PL_sv_undef as "free" and replaces it with a new (undefined) scalar on fetch. This causes the pad code to re-use a slot that was really in use\, hence why the text of the warning message (another constant in the pad) appears when undef was expected.

The patch will be integrated into perl 5.8.9. I don't know why 5.6.1 doesn't show this bug.

Nicholas Clark

Change 26494 by nicholas@​nicholas-saigo on 2005/12/26 23​:10​:53

  Don't try to store PL_sv_undef in pads. (For now)

Affected files ...

... //depot/perl/op.c#739 edit

Differences ...

==== //depot/perl/op.c#739 (text) ====

@​@​ -6794\,6 +6794\,18 @​@​   SvREADONLY_on(PAD_SVl(ix));   SvREFCNT_dec(cSVOPo->op_sv);   } + else if (o->op_type == OP_CONST + && cSVOPo->op_sv == &PL_sv_undef) { + /* PL_sv_undef is hack - it's unsafe to store it in the + AV that is the pad\, because av_fetch treats values of + PL_sv_undef as a "free" AV entry and will merrily + replace them with a new SV\, causing pad_alloc to think + that this pad slot is free. (When\, clearly\, it is not) + */ + SvOK_off(PAD_SVl(ix)); + SvPADTMP_on(PAD_SVl(ix)); + SvREADONLY_on(PAD_SVl(ix)); + }   else {   SvREFCNT_dec(PAD_SVl(ix));   SvPADTMP_on(cSVOPo->op_sv);

p5pRT commented 18 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 18 years ago

From Markus.Herber@eds.com

Hi\,

Good news​: I added the below patch code and the bug vanished. No more strange messages on "make test" for IO-Tty-1.02 and Expect-1.15.

Again I added the "print Dumper &TIOCSCTTY();print Dumper &TIOCSCTTY();" to Pty.pm and also these two correctly report undef two times.

I'm glad I could contribute a tiny piece\, and thank you a lot for the "turbo speed patch" :)

Markus Herber

-----Original Message----- From​: Nicholas Clark via RT [mailto​:perlbug-followup@​perl.org] Sent​: Wednesday\, March 22\, 2006 7​:26 PM To​: Herber\, Markus Subject​: Re​: [perl #38783] Constants with undef value deliver arbitrary value at first call

On Wed\, Mar 22\, 2006 at 03​:08​:49AM -0800\, Markus. Herber @​ eds. com wrote​:

I'm installing perl on an x86 Solaris 10 machine using gcc 3.4.6 and found a strange behaviour which I think is a bug in perl 5.8.x​:

Constants defined via XS are not as constant as expected for the perl 5.8.x series. I found following bug with 5.8.8\, 5.8.7\, and 5.8.2\, but not with 5.6.1 and 5.6.2\, (except for 5.6.1 all with gcc 3.4.6) when installing IO​::Tty version 1.02​:

I put following code in front of the first if(...) it and found out\, that when TIOCSCTTY called first time it returns the string which is argument to the next following warn()​:

use Data​::Dumper; print STDERR Dumper TIOCSCTTY; print STDERR Dumper TIOCSCTTY;

I got following output (and the warning vanished)​:

... $VAR1 = 'Error​: could not connect pty as controlling terminal! '; $VAR1 = undef; ok 2 ...

If I replace the first if(...) by if(0) I get a similar warning for TCSETCTTY from the elsif() part. This constant should also be undef. Thus the effect is not limited to one constant.

I found their definition in xssubs.c after 'perl Makefile.PL'​: ... newCONSTSUB(stash\, "TCSETCTTY"\, &PL_sv_undef); ... newCONSTSUB(stash\, "TIOCSCTTY"\, &PL_sv_undef); ...

Unfortunately I have no deeper insight in perl internals to efficiently debug this further.

Thanks for this bug report and an excellent description of how things seem to be going wrong.

I can't recreate this on FreeBSD with threads\, but I think I know what the problem is. I think it's something I hit upon before Christmas while working on improving how constants are stored. Whilst it bit me with my changes\, I didn't think that it was important with existing code\, as there was no way of triggering it with C\. I'd not thought of XS modules using newCONSTSUB with &PL_sv_undef.

I think that the appended patch will solve the bug. The problem arises when PL_sv_undef ends up being stored as a constant in a pad. It seems to be that the pad code thinks that this pad slot is free\, because the array code treats a pointer to PL_sv_undef as "free" and replaces it with a new (undefined) scalar on fetch. This causes the pad code to re-use a slot that was really in use\, hence why the text of the warning message (another constant in the pad) appears when undef was expected.

The patch will be integrated into perl 5.8.9. I don't know why 5.6.1 doesn't show this bug.

Nicholas Clark

Change 26494 by nicholas@​nicholas-saigo on 2005/12/26 23​:10​:53

  Don't try to store PL_sv_undef in pads. (For now)

Affected files ...

... //depot/perl/op.c#739 edit

Differences ...

==== //depot/perl/op.c#739 (text) ====

@​@​ -6794\,6 +6794\,18 @​@​   SvREADONLY_on(PAD_SVl(ix));   SvREFCNT_dec(cSVOPo->op_sv);   } + else if (o->op_type == OP_CONST + && cSVOPo->op_sv == &PL_sv_undef) { + /* PL_sv_undef is hack - it's unsafe to store it in the + AV that is the pad\, because av_fetch treats values of + PL_sv_undef as a "free" AV entry and will merrily + replace them with a new SV\, causing pad_alloc to think + that this pad slot is free. (When\, clearly\, it is not) + */ + SvOK_off(PAD_SVl(ix)); + SvPADTMP_on(PAD_SVl(ix)); + SvREADONLY_on(PAD_SVl(ix)); + }   else {   SvREFCNT_dec(PAD_SVl(ix));   SvPADTMP_on(cSVOPo->op_sv);

p5pRT commented 18 years ago

From allen@grumman.com

On Mon\, 27 Mar 2006\, Herber\, Markus wrote​:

Hi\,

Good news​: I added the below patch code and the bug vanished. No more strange messages on "make test" for IO-Tty-1.02 and Expect-1.15.

Again I added the "print Dumper &TIOCSCTTY();print Dumper &TIOCSCTTY();" to Pty.pm and also these two correctly report undef two times.

I'm glad I could contribute a tiny piece\, and thank you a lot for the "turbo speed patch" :)

Markus Herber

Ditto for me on AIX 5.1 with perl588. I had previously reported this same problem under the thread "possible constant sub optimizer bug?" but could not elucidate the problem well enough to trigger someone's patching instinct. I'm glad you were able to :-)

John.

p5pRT commented 18 years ago

@iabyn - Status changed from 'open' to 'resolved'