Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conflict in defining constant INIT with INIT blocks results in weird errors #10770

Closed
p5pRT opened this issue Oct 27, 2010 · 9 comments
Closed

Conflict in defining constant INIT with INIT blocks results in weird errors #10770

p5pRT opened this issue Oct 27, 2010 · 9 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Oct 27, 2010

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

Searchable as RT78634$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Oct 27, 2010

From voropaev.andrey@gmail.com

Created by voropaev.andrey@gmail.com

One of my modules was defining constant INIT. After switching to perl5.12 the module
stopped working and the error was

Undefined subroutine &main​::Needed called.
INIT failed--call queue aborted.

This didn't make any sense because there's no such function Needed in my module. I could
reduce the code to the following code

###########################################################
use strict;

MyPackage​::close_cnx();

package MyPackage;
use strict;

use constant INIT => 4;

sub close_cnx
{
  my $self = shift;
  init_action($self);
}

sub init_action
{
  my $self = shift;
  return if $self->{Needed} <= $self->{count};
  callit($self->{ID}, INIT);
}
#####################################################

The funniest thing is, if you switch the positions of init_action and close_cnx functions,
then no error is displayed and perl runs fine.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.12.2:

Configured by Gentoo at Mon Oct 25 11:45:43 CEST 2010.

Summary of my perl5 (revision 5 version 12 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=2.6.34-gentoo-r11, archname=x86_64-linux
    uname='linux vandal 2.6.34-gentoo-r11 #2 mon oct 11 16:13:47 cest 2010 x86_64 amd athlon(tm) 64 processor 3200+ authenticamd gnulinux '
    config_args='-des -Duseshrplib -Darchname=x86_64-linux -Dcc=x86_64-pc-linux-gnu-gcc -Doptimize=-march=athlon64 -O2 -pipe -Dldflags=-Wl,-O1 -Wl,--as-needed -Dprefix=/usr -Dsiteprefix=/usr -Dvendorprefix=/usr -Dscriptdir=/usr/bin -Dprivlib=/usr/lib64/perl5/5.12.2 -Darchlib=/usr/lib64/perl5/5.12.2/x86_64-linux -Dsitelib=/usr/lib64/perl5/site_perl/5.12.2 -Dsitearch=/usr/lib64/perl5/site_perl/5.12.2/x86_64-linux -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.12.2 -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/share/man/man1 -Dsiteman3dir=/usr/share/man/man3 -Dvendorman1dir=/usr/share/man/man1 -Dvendorman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3pm -Dlibperl=libperl.so.5.12.2 -Dlocincpth=  -Duselargefiles -Dd_semctl_semun -Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@localhost -Dinstallusrbinperl=n -Ud_csh -Uusenm -Di_ndbm -Di_gdbm -Di_db -DDEBUGGING=none -Dinc_version_list=
 5.12.1/x86_64-linux 5.12.1 5.12.0/x86_64-linux 5.12.0  -Dusrinc=/usr/include -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='x86_64-pc-linux-gnu-gcc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-march=athlon64 -O2 -pipe',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector'
    ccversion='', gccversion='4.4.4', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='x86_64-pc-linux-gnu-gcc', ldflags ='-Wl,-O1 -Wl,--as-needed -fstack-protector'
    libpth=/usr/local/lib64 /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.11.2.so, so=so, useshrplib=true, libperl=libperl.so.5.12.2
    gnulibc_version='2.11.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -march=athlon64 -O2 -pipe -fstack-protector -Wl,-O1 -Wl,--as-needed'

Locally applied patches:
    0001-gentoo_MakeMaker-RUNPATH.diff
    0002-gentoo_config_over.diff
    0003-gentoo_cpan_definstalldirs.diff
    0004-gentoo_cpanplus_definstalldirs.diff
    0005-gentoo_create-libperl-soname.diff
    0006-gentoo_MakeMaker-delete_packlist.diff
    0007-fixes_8d66b3f9_h2hp_fix.diff


@INC for perl 5.12.2:
    /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux
    /usr/lib64/perl5/site_perl/5.12.2
    /usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux
    /usr/lib64/perl5/vendor_perl/5.12.2
    /usr/lib64/perl5/5.12.2/x86_64-linux
    /usr/lib64/perl5/5.12.2
    /usr/lib64/perl5/site_perl
    /usr/lib64/perl5/vendor_perl
    .


Environment for perl 5.12.2:
    HOME=/home/andrei
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.4.3:/usr/games/bin:/opt/Adobe/Reader8/bin:/opt/java/jdk1.6.0_03/bin:/opt/Adobe/Reader8/bin:/opt/java/jdk1.6.0_03/bin
    PERL_BADLANG (unset)
    SHELL=/bin/zsh

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Oct 28, 2010

From @ikegami

A simpler test case​:

$ perl -le'use constant INIT => 4; print(INIT);'
Undefined subroutine &IO​::File​::AUTOLOAD called.
INIT failed--call queue aborted.

Surprisingly, no problems with BEGIN.

$ perl -le'use constant BEGIN => 4; print(BEGIN);'
4

constant issues a warning for those if warnings are in use.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Oct 28, 2010

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

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 14, 2010

From @cpansprout

On Wed Oct 27 01​:21​:39 2010, voropaev.andrey@​gmail.com wrote​:

One of my modules was defining constant INIT. After switching to
perl5.12 the module
stopped working and the error was

Undefined subroutine &main​::Needed called.
INIT failed--call queue aborted.

This didn't make any sense because there's no such function Needed in
my module. I could
reduce the code to the following code

###########################################################
use strict;

MyPackage​::close_cnx();

package MyPackage;
use strict;

use constant INIT => 4;

sub close_cnx
{
my $self = shift;
init_action($self);
}

sub init_action
{
my $self = shift;
return if $self->{Needed} <= $self->{count};
callit($self->{ID}, INIT);
}
#####################################################

The funniest thing is, if you switch the positions of init_action and
close_cnx functions,
then no error is displayed and perl runs fine.

This was caused by​:

commit f746176
Author​: Zefram <zefram fysh.org>
Date​: Sun Nov 8 15​:03​:45 2009 +0100

  Bareword sub lookups

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 14, 2010

From [Unknown Contact. See original ticket]

On Wed Oct 27 01​:21​:39 2010, voropaev.andrey@​gmail.com wrote​:

One of my modules was defining constant INIT. After switching to
perl5.12 the module
stopped working and the error was

Undefined subroutine &main​::Needed called.
INIT failed--call queue aborted.

This didn't make any sense because there's no such function Needed in
my module. I could
reduce the code to the following code

###########################################################
use strict;

MyPackage​::close_cnx();

package MyPackage;
use strict;

use constant INIT => 4;

sub close_cnx
{
my $self = shift;
init_action($self);
}

sub init_action
{
my $self = shift;
return if $self->{Needed} <= $self->{count};
callit($self->{ID}, INIT);
}
#####################################################

The funniest thing is, if you switch the positions of init_action and
close_cnx functions,
then no error is displayed and perl runs fine.

This was caused by​:

commit f746176
Author​: Zefram <zefram fysh.org>
Date​: Sun Nov 8 15​:03​:45 2009 +0100

  Bareword sub lookups

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 16, 2010

From zefram@fysh.org

Father Chrysostomos via RT wrote​:

use constant INIT => 4;

There's a problem with this line​: INIT, as a subroutine name, is magic
to Perl, and defining a constant in this way actually amounts to defining
a subroutine. If you change the name to XNIT then nothing funny happens.

With the name INIT, funny stuff happens. At some point the constant,
represented specially in the stash, is liable to get upgraded to a
full glob and subroutine. gv_init() invokes newCONSTSUB() to build
the full subroutine, but building it triggers the magic behaviour of
process_special_blocks(). Part of this magic behaviour is to remove
the sub from the glob that it's just been attached to, which makes
gv_init() fail its assertion (on a debugging build) that the sub was
properly attached.

I'm not clear on how &Needed gets involved. That part of the reported
behaviour has all the hallmarks of an object address getting reused such
that an uncounted reference ends up referring to something unexpected.

I believe the fingering of the bareword sub lookup patch is a red herring.
The reason why it's come up is that it added a new situation in which
*INIT would be upgraded to a real glob. Now, the upgrading occurs as
a temporary measure while the use of the INIT constant (in the callit
expression) is being processed at compile time. Formerly, no upgrading
would occur in the compilation of your script. You can also trigger
upgrading by putting "our $INIT" somewhere in the script. However,
in my tests, a non-debugging 5.10 did not visibly misbehave when "our
$INIT" was included to trigger upgrading.

-zefram

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 26, 2010

From @cpansprout

Fixed by 75bd28c.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 26, 2010

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

@p5pRT p5pRT closed this Nov 26, 2010
@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 24, 2010

From @ap

* Zefram <zefram@​fysh.org> [2010-11-16 23​:00]​:

Father Chrysostomos via RT wrote​:

use constant INIT => 4;

There's a problem with this line​: INIT, as a subroutine name,
is magic to Perl, and defining a constant in this way actually
amounts to defining a subroutine. If you change the name to
XNIT then nothing funny happens.

It seems to me that `constant` should warn about this (as well
as all the other special names (`BEGIN`, `END`, `CHECK` etc.)).

For some reason I even feel it should maybe die… but since
const subs aren’t likely to have any side effects I can’t find
any reason to back up my gut feeling and it seems to fall under
“give them rope”.

Regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant