http://qs321.pair.com?node_id=779726

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

Hola, all:

Last week I added fastcgi to my development server and now code which was essentially working is churning out errors like:

Can't locate object method "_any_method_I_call" via package
This code under development is organized as follows:

My::Module My::Module::Foo My::Module::Bar My::Module::Baz
My::Module begins:

package My::Module; use warnings; use strict; . . . use My::Module::Foo qw( :all ); use My::Module::Bar qw( :all ); use My::Module::Baz qw( :all );
and each of those modules begins:

package My::Module::Foo; use strict; use warnings; use Exporter; our @EXPORT = qw( this_method that_method ); our %EXPORT_TAGS = ( all => [qw( this_method that_method )] );
I have been able to restore some functionality by fully qualifying my method calls like so:

My::Module::Foo::this_method($self,@args);
But there are 106 mostly working methods in this application so far and it is still growing. I would love not to have to rewrite every method call in the package in this way. Can anyone please advise me what is the matter here and what I could do about this?

Any clues appreciated.

-- Hugh

UPDATE:

Thanks to a remark in ikegami's post below, I went back into each of my use'd modules and changed them like so:

- use Exporter; + use Exporter qw( import );
The result is that my code seems to work again. Thank you everyone who contributed to this discussion. Even those posts which did not immediately resolve this taught me quite a bit about the innards of perl. I had heard often of the symbol table, but had never known how to access it before. I suspect that should prove invaluable in the future. Thank you ikigami, perrin, esper, and how ever many anonymous monks may have contributed to this discussion.

I'm still curious why the pre-patch version worked before the dist-upgrade, but not after. But I'm grateful to be moving forward again. I'm hopeful I may yet have this code ready for a public launch at next weekend's conference. We shall see.

if( $lal && $lol ) { $life++; }

Replies are listed 'Best First'.
Re: fastcgi broke my Exports
by perrin (Chancellor) on Jul 13, 2009 at 19:44 UTC
    Your example code looks ok. Could you tell us more about how you run FastCGI, i.e. which perl module you're using?
      Thanks perrin:

      I should have clarified. This application is still running under mod_cgi (or at least that was my intention). I installed fastcgi to run a couple of instances of RequestTracker on the same machine. The RT vhost container looks like this:

      <VirtualHost 192.168.1.5:80> ServerName rt1.example.com DocumentRoot /usr/local/rt-3.8.4/share/html CustomLog /var/log/apache2/rt1_access.log combined ErrorLog /var/log/apache2/rt1_error.log AddHandler fastcgi-script fcgi ScriptAlias / /usr/local/rt-3.8.4/bin/mason_handler.fcgi/ </VirtualHost>
      I would like to run this new application under fastcgi one of these days, but it was written as a CGI application and I had not counted on having to refactor this code just yet, just to host RT on the same box where I'm building this.

      Is it not possible to run mod_cgi and mod_fastcgi at the same time on the same apache server? And if not, can anyone recommend a good tutorial to guide such a refactoring of essentially working code? I was well on the path to a beta launch before this little hickup.

      -- Hugh

      if( $lal && $lol ) { $life++; }
        There's no reason this should interfere with existing CGI code if you run them on separate virtualhosts. If you comment this out, do your scripts start working again?
Re: fastcgi did NOT break my Exports, issue now resolved
by ikegami (Patriarch) on Jul 15, 2009 at 23:07 UTC

    I'm still curious why the pre-patch version worked before the dist-upgrade, but not after.

    Versions of Exporter?

    Maybe Exporter was exporting import by default and it stopped?

    By the way, Exporter didn't export import at all, once upon a time.

Re: fastcgi broke my Exports
by ikegami (Patriarch) on Jul 15, 2009 at 22:26 UTC
    You're going into such details, but you haven't even covered the basics yet.
    • You aren't using Exporter. Well, you're loading it, but you don't do anything with it as far as you've shown. You need to import import from Exporter or setup an inheritance relationship. You haven't shown either.

    • You're also didn't specify from which package you issued the call that resulted in the error.

    • You haven't shown or even claimed that you do use My::Module::Foo; from that package.

    I have no problem reproducing the error from what you've told us:

    $ cat Foo.pm package Foo; use strict; use warnings; use Exporter; our @EXPORT = qw( this_method that_method ); our %EXPORT_TAGS = ( all => [qw( this_method that_method )] ); sub this_method_that_method { "Hello World" } 1; $ cat a.pl use strict; use warnings; use Foo; print this_method_that_method(), "\n"; $ perl a.pl Undefined subroutine &main::this_method_that_method called at a.pl lin +e 6.

    By the way, dumping the symbol table is of limited usefulness. It's just too easy to create the entry whose existence you want to check. And the existence of an entry doesn't say anything about whether a sub is associated with that name. And even if you verified the existence of a sub, you still don't know if that sub has been defined.

Re: fastcgi broke my Exports
by hesco (Deacon) on Jul 15, 2009 at 13:50 UTC
    Here is the requested debug output. It has been cleansed to honor an NDA related to the nature of this application, prior to its launch.

    Thank you all for your guidance on this.

    DEBUG: Our path is:

    Wed Jul 15 01:43:45 2009: main, at line 68 in /usr/lib/cgi-bin/beta/index says: DEBUG: Our included files so far are:

    Wed Jul 15 01:43:45 2009: main, at line 69 in /usr/lib/cgi-bin/beta/index says: DEBUG: Our environment is:

    Wed Jul 15 01:43:45 2009: main, at line 70 in /usr/lib/cgi-bin/beta/index says: DEBUG: The symbol table includes:

    Can't locate object method "_GenerateAccountSummary" via package "My:: +Module" at \t/usr/lib/cgi-bin/beta/index line 74 (#1) (F) You called a method correctly, and it correctly indicated a pa +ckage functioning as a class, but that package doesn't define that parti +cular method, nor does any of its base classes. See perlobj. Uncaught exception from user code: \tCan't locate object method "_GenerateAccountSummary" via package "My +::Module" at /usr/lib/cgi-bin/beta/index line 74. at /usr/lib/cgi-bin/beta/index line 74 Premature end of script headers: index
    Hope someone can help me figure out what I'm looking for here; and can suggest reasons why My::Module:: fails to appear in the symbol table, although it is in %INC, suggesting the modules have been loaded.

    if( $lal && $lol ) { $life++; }
      It is in symbol table, just not the way you expect
      'My::' => *{'::My::'},
      You want to look at  %My::Module::

      Actually you want to grep @INC for _GenerateAccountSummary

        Dumping %My::Module:: yields:

        'Account::' => *{'My::Module::Account::'},
        which includes the supposedly missing method.

        Do you mean perhaps that I ought to grep %INC for that method name? @INC includes only directory names, an unlikely place for a method name to hide out.

        Imagining that, I added this to my index script:

        { $ENV{PATH} = "/bin"; foreach my $module (keys %INC){ if($module =~ m/Account/){ print STDERR "The next module is: $module \n"; print STDERR `grep _GenerateAccountSummary $INC{$module}`; print STDERR "\n\n"; } } }
        which yielded this output:

        The next module is: My/Module/Account.pm our @EXPORT = qw( . . . _GenerateAccountSummary . . . ); our %EXPORT_TAGS = ( all => [qw( . . . _GenerateAccountSummary . . . + )] ); sub _GenerateAccountSummary {
        That is the expected result. Still stumped here.

        -- Hugh

        if( $lal && $lol ) { $life++; }
Re: fastcgi broke my Exports
by dsheroh (Monsignor) on Jul 14, 2009 at 09:38 UTC
    Have you tried importing your functions by name (e.g., use My::Module::Foo qw(this_method that_method)) instead of with :all? That should at least get you appropriate error messages if your perl thinks the individual functions aren't being exported.
Re: fastcgi broke my Exports
by hesco (Deacon) on Jul 15, 2009 at 06:03 UTC
    OK, perhaps this is significant. Not a one of the modules which are a part of this package I am developing are reported as a part of the symbol table, %::. Even though they are all listed in the %INC. Why would that be?

    -- Hugh

    if( $lal && $lol ) { $life++; }
      Please show us the dump output. Maybe you want to examine also %My::Module::
Re: fastcgi broke my Exports
by hesco (Deacon) on Jul 15, 2009 at 05:55 UTC
    Thanks perrin, esper and the anonymous monk who have offered ideas for how to unravel this issue. In the morning, after some sleep I will try adding the Devel::Trace to the mix. In the mean time I used my ->log() method to dump @INC, %INC, %ENV and %::.

    I have no idea what '%::' is about, and it does not seem to be documented in my pocket reference, either. %INC includes both my base class and the modules from which they import those ':all' tags (among many other dependencies). I commented out the use ::Account qw( :all );, in favor of a use ::Account qw( _GenerateAccountSummary );. But I still am getting this same error -- that it Can't locate object method "_GenerateAccountSummary" via package.

    What is '%::'? And what should I be looking for in its content?

    Do these results suggest anything to you folks? I'd really love to get past this issue. I have a few issues besides this one left to iron out, and was hoping to unveil this application when I present at a conference next Thursday. I was distracted by other work today, but hope to return to this issue in the morning.

    -- Hugh

    if( $lal && $lol ) { $life++; }