Perl / perl5

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

undefing *foo{CODE} does not fully work #8102

Closed p5pRT closed 14 years ago

p5pRT commented 19 years ago

Migrated from rt.perl.org#37128 (status was 'rejected')

Searchable as RT37128$

p5pRT commented 19 years ago

From @btilly

Created by btilly@gmail.com

This problem has been seen on Perl 5.8.3 and 5.8.7. I assume that it happens under other versions as well.

If you try to undef the CODE slot of a glob\, it only halfway works. ref(*foo{CODE}) will still show that it is a code reference\, and UNIVERSAL​::can still shows that it is a code reference.

This bug causes problems when Apache​::Reload and Class​::DBI are used together.

The following code sample demonstrates what I am talking about

-------- #! /usr/bin/perl -l print "Originally foo() is a " . ref(*foo{CODE}); print "Initializing foo()"; *foo = sub {print "hello"}; print "foo() is now a " . ref(*foo{CODE}); print "According to can\, foo is " . main->can("foo"); print "Calling foo()"; foo();

print "Undefining foo()"; $x = *foo; undef &$x; print "foo() is now a " . ref(*foo{CODE}); print "According to can\, foo is " . main->can("foo"); print "Calling foo()"; foo();

__END__ Originally foo() is a Initializing foo() foo() is now a CODE According to can\, foo is CODE(0x8175b24) Calling foo() hello Undefining foo() foo() is now a CODE According to can\, foo is CODE(0x8175b24) Calling foo() --------

The way that this comes into play in the case that I mention is that Apache​::Reload attempts to undefine subroutines that have been defined\, but when Class​::DBI tries to check whether they are there it is told that they are\, with disasterous results.

Perl Info ``` Flags: category=core severity=medium Site configuration information for perl v5.8.3: Configured by Debian Project at Sun Feb 15 17:22:09 EST 2004. Summary of my perl5 (revision 5.0 version 8 subversion 3) configuration: Platform: osname=linux, osvers=2.4.22-xfs+ti1211, archname=i386-linux-thread-multi uname='linux kosh 2.4.22-xfs+ti1211 #1 sat oct 25 10:11:37 est 2003 i686 gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.3 -Dsitearch=/usr/local/lib/perl/5.8.3 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.3 -Dd_dosuid -des' 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='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O3', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='3.3.3 20040125 (prerelease) (Debian)', 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 libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so.5.8.3 gnulibc_version='2.3.2' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.3: /etc/perl /usr/local/lib/perl/5.8.3 /usr/local/share/perl/5.8.3 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl /usr/local/lib/perl/5.8.2 /usr/local/share/perl/5.8.2 /usr/local/lib/perl/5.8.1 /usr/local/share/perl/5.8.1 /usr/local/lib/perl/5.8.0 /usr/local/share/perl/5.8.0 . Environment for perl v5.8.3: HOME=/home/btilly LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH=/usr/local/oracle/lib LOGDIR (unset) PATH=/home/btilly/cvs/bin:/home/btilly/cvs/lib/oracle/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/usr/share/games:~/cvs/bin:/usr/local/oracle/bin PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 19 years ago

From @iabyn

On Fri\, Sep 09\, 2005 at 06​:11​:49PM -0700\, Ben Tilly wrote​:

If you try to undef the CODE slot of a glob\, it only halfway works. ref(*foo{CODE}) will still show that it is a code reference\, and UNIVERSAL​::can still shows that it is a code reference.

Undefing a sub is not the same as deleting a sub. Internally\, the CV continues to exist\, but its pad and op tree are freed. cf​:

  $ perl587 -le 'my $x = []; undef @​$x; print $x'   ARRAY(0x9c7d180)   $ perl587 -le 'my $x = sub {}; undef &$x; print $x'   CODE(0x8e40bac)

In both cases the thing continues to exist\, but has no useful 'value'.

-- My get-up-and-go just got up and went.

p5pRT commented 19 years ago

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

p5pRT commented 19 years ago

From @btilly

When I looked at the way the message appeared on the list\, I realized that I forgot to include one line of output. The one where it dies. Here is the program and output with that additional piece of information.

And to clarify the Class​::DBI/Apache​::Reload conflict that this causes\, load up the page and look at it. You see a web page. Make a trivial modification to the underlying code. You get internal server errors because it can't figure out that there aren't really accessors there for it to go and call.

Cheers\, Ben

#! /usr/bin/perl -l print "Originally foo() is a " . ref(*foo{CODE}); print "Initializing foo()"; *foo = sub {print "hello"}; print "foo() is now a " . ref(*foo{CODE}); print "According to can\, foo is " . main->can("foo"); print "Calling foo()"; foo();

print "Undefining foo()"; $x = *foo; undef &$x; print "foo() is now a " . ref(*foo{CODE}); print "According to can\, foo is " . main->can("foo"); print "Calling foo()"; foo();

__END__ Originally foo() is a Initializing foo() foo() is now a CODE According to can\, foo is CODE(0x8158f10) Calling foo() hello Undefining foo() foo() is now a CODE According to can\, foo is CODE(0x8158f10) Calling foo() Not a CODE reference at - line 16.

p5pRT commented 19 years ago

From @rgarcia

On 9/10/05\, Dave Mitchell \davem@​iabyn\.com wrote​:

Undefing a sub is not the same as deleting a sub. Internally\, the CV continues to exist\, but its pad and op tree are freed. cf​:

One of the items on the todo list is to allow the construct

  delete &foo;

I could finish my patch to do it if I could figure out how to delete a CV cleanly from all the stashes where it's referenced... (subs have this tendency to be exported in other stashes.)

p5pRT commented 14 years ago

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