in reply to Re: RFC : Pragma vs. Module
in thread RFC : Pragma vs. Module

Could you please elaborate on why you can't/shouldn't use INIT with mod_perl? I have never heard of that restriction before, although to be honest, I have never looked either (or ever had a reason too look).

-stvn

Replies are listed 'Best First'.
Re: Re: Re: RFC : Pragma vs. Module
by liz (Monsignor) on Mar 14, 2004 at 22:37 UTC
    The problem can be easily described with the following code:
    use warnings; eval "INIT { 1 }"; __END__ Too late to run INIT block at (eval 1) line 1.
    mod_perl basically loads all modules as a string eval. And you can't have INIT code blocks in eval. See also the CGI to mod_perl Porting. mod_perl Coding guidelines.

    I faced a similar dilemma with Thread::Bless: in the end I made sure initializations would only actually initialize once (even if called multiple times), renamed the INIT code block to sub unitialize and added an INIT block that just does a goto &initialize.

    Liz

      Liz,

      My apologies. You are completely correct, INIT and CHECK will not run anywhere in mod_perl. I checked every possible situation I could think of in one of my current mod_perl projects, and nothing worked. So I will now put my foot in my mouth.

      Apparently even modules loaded with PerlModule and PerlRequire are at some level eval-ed. Which to me seems ugly, but not being a C programmer or Stas Beckmen, who am I to complain.

      After some reading though, it seems to me that the PerlRestartHandler and PerlChildInitHandler could potentially be used to accomplish similar functionality. PerlRestartHandler happens before Apache pre-forks all the children, and PerlChildInitHandler runs at the begining of each child process. Has anyone ever tried to use these as CHECK/INIT replacements?

      -stvn
        These pseudohandlers could offer the right timing semantics, I guess. But how do you go about actually calling the CHECK and INIT blocks? Trying to call Foo::INIT() is a runtime error, because no such subroutine exists. I opine that it was a mistake to allow a sub INIT {} syntax, because their semantics are entirely distinct from subroutines — in particular, you can define any number of INIT or other special blocks and they'll accumulate, instead of overriding previous ones.

        Makeshifts last the longest.

      Liz,

      This makes sense that any of the compilation phases BEGIN, CHECK, INIT etc. would not work 100% as expected when eval-ed. They are for affecting the compilation during compile-time, and eval is a run-time construct.

      As for the assertion that this will not work with mod_perl, you are partially right. To start, Apache::Registry and similar CGI-to-mod_perl tools do eval the files as strings in order to run them in the persistant mod_perl environment. But this is only one very small (but very commonly used) aspect of mod_perl. The rest of mod_perl is handlers (for each of the Apache request cycles), and while I have not tested this assertion, I am pretty sure that INIT blocks as well as BEGIN, CHECK & END all run perfectly fine.

      -stvn

      UPDATE:
      Wow, was I wrong. Apparently mod_perl evals everything, handlers and all, see my apology to Liz below.

        BEGIN and END work in eval "". It's just CHECK and INIT that have to be set up before the compile of the main script ends or they are "too late".