develooper Front page | perl.perl5.porters | Postings from April 2000

[ID 20000409.003] Disappearing constant values

Thread Next
From:
eric
Date:
April 9, 2000 21:21
Subject:
[ID 20000409.003] Disappearing constant values
Message ID:
E12eVhT-0007Lp-00@mail.xmission.com
This is a bug report for perl from eblood@xmission.com,
generated with the help of perlbug 1.28 running under perl v5.6.0.


-----------------------------------------------------------------
[Please enter your report here]

When useithreads is defined, the following code does not generate
a 'Modification of a read-only value attempted' error like it does
in perl5.005_03.

  sub C () { 1 }
  sub M { $_[0] = 2; }
  eval "C";
  M(C);

The following code shows a much more serious consequence of the
same bug.

  sub C () { 1 }
  sub M { M() if defined(C); }
  eval "C";
  M(C);

This code should go into infinite recursion.  However in
perl5.6.0 using ithreads it drops out of recursion after
the second iteration because C becomes undefined.

This is caused by a number of interacting pieces of code as follows:

  1. When the tokenizer encounters a bareword whose definition
     is a constant sub, it gets the SV for the constant in the
     sub and puts it in the op_sv field of the opcode
     (after incrementing the SV's reference count).
     As a result multiple opcodes may all point to the same SV.
  2. Peep moves this SV to the pad.  When it does so it sets the
     SVs_PADTMP flag.  At this point multiple pad slots may all
     be pointing to the same SV.
  3. Opcodes sometimes get cleared before the end of the program
     (when they are were generated by eval or by the main body
     of a module).  When the opcode is cleared it calls pad_free
     on it's op_targ value.
  4. pad_free clears the SVs_PADTMP and SVs_READONLY flags on the
     SV.  Unfortunately this SV may also be used in other pads.
  5. When a procedure recurses it copies the pad constants but
     only if the associated SV is read-only.  Since the read-only
     flag was cleared by pad_free the constant doesn't get copied
     and appears as undef in the recursive call.

I can see several possible solutions but I'm not sure which
approach to take.  I'm willing to write a patch but I'd like
some advice on which way to go.  Or if someone with more experience
in the perl core feels they should do this instead that's fine with
me.

These are the possibilities I see:

  1. Have the tokenizer always create a new SV for constant subs.
  2. Have peek copy the constant instead of using it directly when
     it moves it to the pad.
  3. Have pad_free never remove the flags when both SVs_PADTMP and
     SVs_READONLY are set.
  4. Have pad_free only remove the flags when the reference count
     for the SV is 1.

I lean towards 4 or 2.  I think that 4 would be safe but it might
not always free up a pad slot when it should.  2 should also be
safe but would cause additional memory usage.



[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=high
---
Site configuration information for perl v5.6.0:

Configured by eblood at Fri Mar 24 12:36:06 2000.

Summary of my perl5 (revision 5 version 6 subversion 0) configuration:
  Platform:
    osname=MSWin32, osvers=4.0, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    usethreads=undef use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=undef d_sfio=undef uselargefiles=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef
  Compiler:
    cc='cl', optimize='-O1 -MD -DNDEBUG', gccversion=
    cppflags='-DWIN32'
    ccflags ='-O1 -MD -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT  -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DPERL_MSVCRT_READFIX'
    stdchar='char', d_stdstdio=define, usevfork=false
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=4
    alignbytes=8, usemymalloc=n, prototype=define
  Linker and Libraries:
    ld='link', ldflags ='-nologo -nodefaultlib -release  -libpath:"D:\apps\perl56\lib\CORE"  -machine:x86'
    libpth="g:\apps\msdevstd\lib" "g:\apps\msdevstd\mfc\lib" "%lib%" "D:\apps\perl56\lib\CORE"
    libs=  oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib  netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib  version.lib odbc32.lib odbccp32.lib msvcrt.lib
    libc=msvcrt.lib, so=dll, useshrplib=yes, libperl=perl56.lib
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -release  -libpath:"D:\apps\perl56\lib\CORE"  -machine:x86'

Locally applied patches:
    ACTIVEPERL_LOCAL_PATCHES_ENTRY

---
@INC for perl v5.6.0:
    d:\apps\cmt\lib
    D:/apps/perl56/lib
    D:/apps/perl56/site/lib
    .

---
Environment for perl v5.6.0:
    HOME=d:\home
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=d:\apps\perl56\bin;D:\WINNT\system32;D:\WINNT;g:\apps\bor\Delphi5\Projects\Bpl;g:\apps\bor\Delphi5\Bin;d:\apps\perl\bin;d:\apps\cmt\nt;d:\bin\nt;d:\bin;;g:\apps\bor\delphi3\bin;g:\apps\bor\tasm\bin;g:\apps\bor\bp\bin;d:\apps\iqtools;g:\apps\msdevstd\bin\;g:\apps\bor\bcc55\bin;;d:\rnd;c:\APPS\PERL\BIN
    PERLLIB=d:\apps\cmt\lib
    PERL_BADLANG (unset)
    PERL_MAILERS=smtp
    SHELL (unset)

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About