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

Attribute::Handlers not fully functional at runtime #8672

Open
p5pRT opened this issue Nov 7, 2006 · 6 comments
Open

Attribute::Handlers not fully functional at runtime #8672

p5pRT opened this issue Nov 7, 2006 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 7, 2006

Migrated from rt.perl.org#40695 (status was 'open')

Searchable as RT40695$

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2006

From johnpc@xs4all.nl

Created by johnpc@xs4all.nl

When subroutine attributes are used at "runtime", for example
by require()-ing a file with extra function definitions, the
Attribute handlers are called, but with a $symbol reference set
to "ANON" (even though the functions are not anonymous).

This can be worked around by doing the require inside a BEGIN
block (but that is ugly if the requires are dynamic).

As an example, the attached code produces​:

$ perl -w test.pl
(CODE(0x814f7a4)), CODE foo got attribute Loud with data (Boe), in phase CHECK
(CODE(0x81b4b30)), CODE Can't use string ("ANON") as a symbol ref while "strict refs" in use at test.pl line 14.
BEGIN failed--compilation aborted at bar.pl line 5.
Compilation failed in require at test.pl line 34.

test.pl and bar.pl can also be downloaded from
http​://www.xs4all.nl/~johnpc/bug-ah/

test.pl contains​:
---8<------
#!/usr/bin/perl
#

package LoudDecl;
use strict;
use warnings;
use Attribute​::Handlers;

sub Loud :ATTR {
  my ($package, $symbol, $referent, $attr, $data, $phase) = @​_;

  print STDERR "($referent), ", ref($referent), " ";
### comment out next line to make things work
  print STDERR *{$symbol}{NAME}, " ";
  print STDERR "got attribute ${attr} ";
  print STDERR "with data ($data), ";
  print STDERR "in phase $phase\n";
}

package main;

use strict;
use warnings;
our @​ISA;
BEGIN { push @​ISA, 'LoudDecl' };

sub foo :Loud(Boe)
{
  my $arg = shift;
  return "foo $arg";
}

# this works only if inside a BEGIN block​:
require "bar.pl";
# bar.pl contains​:
#sub bar :Loud(Hello)
#{
# my $arg = shift;
# return "bar $arg";
#}
#
#1;
#
#-- or if it is inlined

print foo("hi"), "\n", bar("boo"), "\nDone\n";
--->8------

and bar.pl contains​:
---8<------
sub bar :Loud(Hello)
{
  my $arg = shift;
  return "bar $arg";
}

1;
--->8------

Perl Info

Flags:
    category=library
    severity=medium

Site configuration information for perl v5.8.8:

Configured by Debian Project at Sun Aug  6 15:47:28 UTC 2006.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
  Platform:
    osname=linux, osvers=2.6.15-1-686, archname=i486-linux-gnu-thread-multi
    uname='linux ulises 2.6.15-1-686 #2 mon mar 6 15:27:08 utc 2006 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -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.8 -Dsitearch=/usr/local/lib/perl/5.8.8 -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.8 -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 -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.1.2 20060729 (prerelease) (Debian 4.1.1-10)', 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.6.so, so=so, useshrplib=true, libperl=libperl.so.5.8.8
    gnulibc_version='2.3.6'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.8:
    /etc/perl
    /usr/local/lib/perl/5.8.8
    /usr/local/share/perl/5.8.8
    /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.7
    /usr/local/share/perl/5.8.7
    /usr/local/lib/perl/5.8.4
    /usr/local/share/perl/5.8.4
    /usr/local/lib/perl/5.8.3
    /usr/local/share/perl/5.8.3
    /usr/local/share/perl/5.8.2
    /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.8:
    HOME=/usr/home/johnpc
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/usr/X11R6/bin:/usr/home/johnpc/bin:/sbin:/usr/sbin:/usr/local/sbin
    PERLDOC=-i
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2006

From @rgarcia

On 07/11/06, via RT johnpc @​ xs4all. nl <perlbug-followup@​perl.org> wrote​:

When subroutine attributes are used at "runtime", for example
by require()-ing a file with extra function definitions, the
Attribute handlers are called, but with a $symbol reference set
to "ANON" (even though the functions are not anonymous).

This can be worked around by doing the require inside a BEGIN
block (but that is ugly if the requires are dynamic).

Can't this be also solved by declaring the attribute handler as being
executed at BEGIN time ? eg. with​:
sub Loud :ATTR(BEGIN) { ... }

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2006

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

@p5pRT
Copy link
Author

p5pRT commented Jun 6, 2018

From jkahrman@mathworks.com

I created a patch to try to support this case better. It doesn't provide quite the right semantics for the phases, and it doesn't resolve the issue for attributes tagged for 'END' phases, but it ensures that the attributes for the 'CHECK' (default) and 'INIT' phases aren't silently ignored just because 'Attribute​::Handlers' was loaded after the initial compilation phase.

@p5pRT
Copy link
Author

p5pRT commented Jun 6, 2018

From jkahrman@mathworks.com

AttrHand_require.rt40695.patch
--- perl5.20.2/dist/Attribute-Handlers/lib/Attribute/Handlers.pm	2016-11-03 00:16:14.000000000 -0400
+++ perl5.20.2_patch/dist/Attribute-Handlers/lib/Attribute/Handlers.pm	2016-11-03 00:16:14.000000000 -0400
@@ -1,5 +1,5 @@
 package Attribute::Handlers;
-use 5.006;
+use v5.14;
 use Carp;
 use warnings;
 use strict;
@@ -35,14 +35,19 @@
 my %raw;
 my %phase;
 my %sigil = (SCALAR=>'$', ARRAY=>'@', HASH=>'%');
-my $global_phase = 0;
+
+# Union of possible values of ${^GLOBAL_PHASE} and @global_phases
 my %global_phases = (
-	BEGIN	=> 0,
-	CHECK	=> 1,
-	INIT	=> 2,
-	END	=> 3,
+    CONSTRUCT => -1,
+    START     => 0,
+    BEGIN     => 0,
+    CHECK     => 1,
+    INIT      => 2,
+    RUN       => 3,
+    END       => 4,
+    DESTRUCT  => 9,
 );
-my @global_phases = qw(BEGIN CHECK INIT END);
+my @global_phases = qw(BEGIN CHECK INIT END); # valid phases as args to ATTR
 
 sub _usage_AH_ {
 	croak "Usage: use $_[0] autotie => {AttrName => TieClassName,...}";
@@ -174,9 +179,9 @@
 				    $raw{$handler}, $phase{$handler}, $filename, $linenum];
 			foreach my $gphase (@global_phases) {
 			    _apply_handler_AH_($decl,$gphase)
-				if $global_phases{$gphase} <= $global_phase;
+				if $global_phases{$gphase} <= $global_phases{${^GLOBAL_PHASE}};
 			}
-			if ($global_phase != 0) {
+			if ($global_phases{${^GLOBAL_PHASE}} != 0) {
 				# if _gen_handler_AH_ is being called after 
 				# CHECK it's for a lexical, so make sure
 				# it didn't want to run anything later
@@ -235,7 +240,6 @@
 {
         no warnings 'void';
         CHECK {
-                $global_phase++;
                 _resolve_lastattr if _delayed_name_resolution;
                 foreach my $decl (@declarations) {
                         _apply_handler_AH_($decl, 'CHECK');
@@ -243,7 +247,6 @@
         }
 
         INIT {
-                $global_phase++;
                 foreach my $decl (@declarations) {
                         _apply_handler_AH_($decl, 'INIT');
                 }
@@ -251,7 +254,6 @@
 }
 
 END {
-        $global_phase++;
         foreach my $decl (@declarations) {
                 _apply_handler_AH_($decl, 'END');
         }

@p5pRT
Copy link
Author

p5pRT commented Jun 6, 2018

From @jkeenan

On Wed, 06 Jun 2018 17​:21​:31 GMT, jkahrman@​mathworks.com wrote​:

I created a patch to try to support this case better. It doesn't
provide quite the right semantics for the phases, and it doesn't
resolve the issue for attributes tagged for 'END' phases, but it
ensures that the attributes for the 'CHECK' (default) and 'INIT'
phases aren't silently ignored just because 'Attribute​::Handlers' was
loaded after the initial compilation phase.

Thank you for the patch. My hunch is that we won't be able to use this patch as is, for two reasons​:

1. You've drawn the patch against the version of Attribute​::Handlers distributed with perl-5.20.2 -- approximately version 0.96. But since in the core distribution A​::H is up to version 1.01, the patch probably wouldn't apply cleanly. Would it be possible to re-draw the patch against perl 5 blead, i.e., against a git checkout?

2. While A​::H is now maintained by Perl 5 Porters in the core distribution ("blead-upstream"), it is expected to get independent releases to CPAN to make it available to older versions of Perl. Your patch bumps the minimum version of Perl needed for the module from 5.6 to 14.0. That means that any perl installation of 5.8, 5.10 or 5.12 would be unable to use the module. I suspect that won't fly, but the determination on that would have to be made by the module's listed CPAN maintainer, Steffen Mueller.

As to the patch's actual content, I don't yet have an informed opinion.

Thank you very much.
--
James E Keenan (jkeenan@​cpan.org)

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

No branches or pull requests

2 participants