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

Dear Monks, I have quite a few CGI scripts that with time became slow, so I decided to use Apache::Registry to speed them up. However, I encountered an interesting problem -- automatically generated subroutines get lost. Here's an example I came up with to illustrate the problem:

Dmitri/Test.pm

package Dmitri::Test; INIT { # This does not work under Apache::Registry: *{"Dmitri::Test::ABC::say_hello"} = sub { print "hi\n"; }; *{"Dmitri::Test::ABC::new"} = sub { return bless {}, "Dmitri:: +Test::ABC" ; }; # This works: #sub Dmitri::Test::ABC::say_hello { print "hi\n"; }; #sub Dmitri::Test::ABC::new { return bless {}, "Dmitri::Test:: +ABC"; }; } sub say_hi { my $x = Dmitri::Test::ABC->new; $x->say_hello; } 1;

test.cgi

#!/usr/bin/perl -w use Dmitri::Test; print <<HTML; Content-type: text/plain HTML Dmitri::Test::say_hi; exit(0);

The code runs fine under mod_cgi. Using Apache::Registry, I get this error:

[Wed Nov 6 16:49:12 2002] [error] Can't locate object method "new" via package "Dmitri::Test::ABC" (perhaps you forgot to load "Dmitri::Test::ABC"?) at /usr/lib/perl5/site_perl/5.6.1/Dmitri/Test.pm line 14.

I could theoretically use the second method pointed out in Test.pm code, but the problem is that the routines are generated from code refs, and doing

sub A::B::routine { &$ref }

just causes me mental pain and anguish (inefficient).

I wonder if your collective wisdom could show me the way out of this problem. Many thanks.

Replies are listed 'Best First'.
Re: Apache::Registry losing subs created via globs.
by perrin (Chancellor) on Nov 06, 2002 at 22:23 UTC
    Change the INIT block to a BEGIN block.
      Wow. Could you explain why this happens, please?
        Here is basically what Apache::Registry does to your script, and how to recreate the error:
        my $code = <<EOT; sub abc::def { use Dmitri::Test; print <<HTML; Content-type: text/plain HTML use strict; use warnings; Dmitri::Test::say_hi; } EOT eval $code; abc::def();
        Your 'INIT' in the module would be a valid label if it ended in a ':', or it would be a valid BEGIN block if it said "BEGIN". I'm not sure what it gets parsed as here or why it works in one situation but not the other.

        Update: from perlsyn:

        The LABEL is optional, and if present, consists of an identifier followed by a colon.

        Update: I now see that INIT is a valid block and is in perlcompile and perlmod, though I still wouldn't know for sure why it behaves the way it does in the above situation.

        I just knew that special steps were required to support BEGIN blocks in mod_perl (or any app that embeds Perl) so I thought maybe something special would be required to support INIT as well, and it might not have been done. I've actually never seen an INIT block before. It's a relatively recent addition.
Re: Apache::Registry losing subs created via globs.
by runrig (Abbot) on Nov 06, 2002 at 22:26 UTC
    I'm pretty sure you don't want to exit under mod_perl...
    Though that's probably not the problem if it fails like that the first time you execute it..
      Apache::Registry overrides exit function.
        Downvoting this one? From Apache::Registry man page:

        
        
        ENVIRONMENT
            The Apache function `exit' overrides the Perl core built-
            in function.