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

Update/Punchline: Ultimately, the solution to my problem was to move the PerlPassEnv declaration outside my VirtualHost block. I was baffled by that. I've found a (very old; 2003) thread on the mod_perl mailing list that at least explains "all vhosts inherit PerlPostConfigHandler from the main server and run it." I don't think that's 100% the cause of my issue, but it feels similar and is close enough for me to stop obsessing about this one so I can get back to work on making my package actually work right. (end of update)

I'm converting a CGI script that runs OK into something that will run under mod_perl. It's a feature of the current system that you can swap from prod to dev database and back just by resetting ORACLE_SID in the environment and restarting Apache, so that's something I'd like to keep: the database connection string should come from the environment. I'm not particularly invested in any particular way to do it, except that it would be nice if it were something simple.

The package for connecting to Oracle uses Class::DBI and currently has

__PACKAGE__->set_db( 'main', "dbi:Oracle:$ENV{'ORACLE_SID'}", ...
which runs fine under CGI because we have PassEnv ORACLE_SID in the configuration, and the actual Oracle database is in the environment when Apache starts.

Just doing the "obvious" things of making the handler and putting PerlPassEnv ORACLE_SID, I find that at compile-time, %ENV only contains PATH, MOD_PERL, and MOD_PERL_API_VERSION.

The packages compile just fine, but when it comes time to actually invoke the thing I get errors like

DBI connect('','apacheschcon',...) failed: ORA-12545: Connect failed b +ecause target host or object does not exist (DBD ERROR: OCIServerAtta +ch) at /usr/lib/perl5/site_perl/5.8.8/Ima/DBI.pm line 328
which I interpret as "ORACLE_SID was undef when I got compiled, so now when I try to connect I'm connecting to '', which isn't a database". This despite the fact that, within the handler, I can see ORACLE_SID sitting there in %ENV just fine.

I'm converting a very old CGI to mod_perl, so I didn't expect complete smooth sailing, but this part is irritating me and I can't figure out how to get around it.

Thanks for your help,

dave

PS: In case it's helpful, I've got ENV{MOD_PERL} = mod_perl/2.0.4 and Apache 2.2.3 on a Linux machine with a pretty vanilla RedHat 5 (Enterprise) installation.

My solution: For no particular reason, I decided to move the PerlPassEnv declaration outside the VirtualHost block (Did I mention this was using VirtualHost? Guess not.) Poof! There's the variable at compile-time. So there's, apparently, some interaction between the VirtualHost and the compilation of my packages. I suppose that makes some sense, somehow, but I can't quite say how.

Replies are listed 'Best First'.
Re: How to get environment variables into a mod_perl handler at compile-time?
by InfiniteSilence (Curate) on Feb 07, 2012 at 00:03 UTC

    PerlSetVar doesn't make an environment variable. It makes a value retrievable via the mod_perl API. See dir_config in the mod_perl docs.

    Celebrate Intellectual Diversity

      Thanks for this. It's not what I ended up with, but it was educational. I was puzzled about how to use dir_config at compile-time, but now I've learned about Apache::ServerUtil so that's nice.

      The thing that kept me from using this is that, although I could get some particular value into the script, I couldn't get the environment variable down there. If I added

      PerlSetVar ORACLE_SID production
      in the Apache configuration with my handler, I could add
      if( $ENV{'MOD_PERL'} } ) { require 'Apache2::ServerUtil' ; my $s = Apache2::ServerUtil->new ; $ENV{'ORACLE_SID'} ||= $s->dir_config('ORACLE_SID') ; }
      before the set_db call and thing would basically work. But I couldn't figure out how to pull ORACLE_SID from the environment.
Re: How to get environment variables into a mod_perl handler at compile-time?
by Anonymous Monk on Feb 07, 2012 at 12:34 UTC