Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have inherited an application that has 70+ packages/modules. For security reasons, I cannot post code. But, I don't necessarily need help finding the problem. Rather, I need help with a strategy to find the problem.

When I run this application, I get a series of warnings that look like:

    Subroutine someSubNameHere redefined at /some/path/to/moduleName.pm line someLineNumberHere.

This happens for one package (call it fileB.pm) and it only happens once. But, the the pattern of 'use' statement chains through the numerous packages is not trivial.

It appears to me that fileA.pm is 'using' fileB.pm which 'uses' fileC.pm which 'uses' fileD.pm which uses fileB.pm, again. When the app starts up it begins to compile fileA, hits the 'use' statement and picks up fileB, hits a 'use' statement and picks up fileC and so on. It finally hits the last 'use' in the chain and loads fileB.pm. At that point it falls back to complete loading fileD, then fileC, then fileB. At that point, the subs in fileB have already been loaded with the associated namespace (fileB) and it warns about redefining them.

At least, that is what I think is happening. My hope is that there is some mechanism for tracking these 'use' chains at compile time (run time is too late).

Any ideas?

I may have to just start at the top and track each 'use' chain until it hits 'fileB.pm' and then, after some sequences of 'use' statements, 'uses' fileB.pm, a second time.

I hate being taunted a second time. (Said with a faux french accent.)(Oblique Monty Python ref.)

Thanks

PS - I've tried to register for the site and I never get a password emailed.... at least, not for several hours.
  • Comment on How to located cause of 'Subroutine SomeSubName redefined...' warnings

Replies are listed 'Best First'.
Re: How to located cause of 'Subroutine SomeSubName redefined...' warnings
by kennethk (Abbot) on Dec 10, 2010 at 19:01 UTC
    perl is smart enough that multiple use statements will not result in the warning you describe - each package will be compiled and each namespace will be populated only once. This includes cases with circular dependency, though resolving that is likely worth your time. My guess is that at some point during a refactor, the programmer forgot to delete the old version of the subroutine in the original module. Something which is the structural equivalent of

    #!/usr/bin/perl use strict; use warnings; use Scalar::Util qw(looks_like_number); sub looks_like_number($) { 1; }

    It may be innocuous, but chances are good that the subroutines are not identical. A simple file search for sub someSubNameHere will likely show you all occurrences and lead you to the appropriate solution.

      Very possible. This will be my next path of pursuit. Thanks.
Re: How to located cause of 'Subroutine SomeSubName redefined...' warnings
by graff (Chancellor) on Dec 11, 2010 at 16:15 UTC
Re: How to located cause of 'Subroutine SomeSubName redefined...' warnings
by Anonymous Monk on Dec 10, 2010 at 18:45 UTC
      No Joy. The 'Subroutine SomeSubName redefined....' warnings happen before the trace output starts. I'll keep looking at Devel::Trace to make sure I'm not missing something.

      It appears to me that -d:Trace is generating output at run time. I need to see what is happening at compile time.... I think.
        Um, compile time can happen at runtime if you use do/require
        $ perl -d:Trace -e" use strict;" $ perl -d:Trace -e" require strict;" >> -e:1: require strict; >> C:/perl/5.10.1/lib/strict.pm:3: $strict::VERSION = "1.04"; >> C:/perl/5.10.1/lib/strict.pm:6: unless ( __FILE__ =~ /(^|[\/\\])\Q$ +{\__PACKAGE__}\E\.pmc?$/ ) { >> C:/perl/5.10.1/lib/strict.pm:6: unless ( __FILE__ =~ /(^|[\/\\])\Q$ +{\__PACKAGE__}\E\.pmc?$/ ) { >> C:/perl/5.10.1/lib/strict.pm:12: my %bitmask = ( >> C:/perl/5.10.1/lib/strict.pm:32: my $default_bits = bits(qw(refs su +bs vars)); >> C:/perl/5.10.1/lib/strict.pm:19: my $bits = 0; >> C:/perl/5.10.1/lib/strict.pm:20: my @wrong; >> C:/perl/5.10.1/lib/strict.pm:21: foreach my $s (@_) { >> C:/perl/5.10.1/lib/strict.pm:22: push @wrong, $s unless exists +$bitmask{$s}; >> C:/perl/5.10.1/lib/strict.pm:23: $bits |= $bitmask{$s} || 0 +; >> C:/perl/5.10.1/lib/strict.pm:22: push @wrong, $s unless exists +$bitmask{$s}; >> C:/perl/5.10.1/lib/strict.pm:23: $bits |= $bitmask{$s} || 0 +; >> C:/perl/5.10.1/lib/strict.pm:22: push @wrong, $s unless exists +$bitmask{$s}; >> C:/perl/5.10.1/lib/strict.pm:23: $bits |= $bitmask{$s} || 0 +; >> C:/perl/5.10.1/lib/strict.pm:25: if (@wrong) { >> C:/perl/5.10.1/lib/strict.pm:29: $bits; >> C:/perl/5.10.1/lib/strict.pm:44: 1; $
Re: How to located cause of 'Subroutine SomeSubName redefined...' warnings
by clueless newbie (Curate) on Dec 11, 2010 at 15:08 UTC
    Being an extremely clueless newbie I wonder if the following approach will work for you.
    #! BEGIN { # Convert the warning to Carp::cluck $SIG{__WARN__} = sub { Carp::cluck(@_); }; }; use Carp; use strict; use warnings; use Mod1; use Mod2; INIT { # Clear the warning to Carp::cluck $SIG{__WARN__}='DEFAULT'; }; sub One { # First definition return "first"; }; sub One { # Second definition return "second"; }; print One()."\n"; exit;
    package Mod1; use Exporter; use strict; use warnings; @Mod1::ISA=qw(Exporter); @Mod1::EXPORT=qw(One); sub One { return "Mod1::One"; }; 1;
    package Mod2; use strict; use warnings; use Mod1; @Mod2::ISA=qw(Exporter); @Mod2::EXPORT=qw(One); sub One { return "Mod1::One"; }; 1;
    Running under Windows 2K/ActiveState 5.10 I get
    C:\Code\SecCage>perl redef.pl Subroutine One redefined at Mod2.pm line 10. at redef.pl line 5 main::__ANON__('Subroutine One redefined at Mod2.pm line 10.\x +{a}') called at Mod2.pm line 10 require Mod2.pm called at redef.pl line 12 main::BEGIN() called at Mod2.pm line 10 eval {...} called at Mod2.pm line 10 Subroutine One redefined at redef.pl line 19. at redef.pl line 5 main::__ANON__('Subroutine One redefined at redef.pl line 19.\ +x{a}') called at redef.pl line 19 Subroutine One redefined at redef.pl line 23. at redef.pl line 5 main::__ANON__('Subroutine One redefined at redef.pl line 23.\ +x{a}') called at redef.pl line 23 second