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

O monks,
I am lost with the following (simplified) script under apache and ModPerl::Registry :
my $lig; ... $lig=4; print STDERR "ligA <<$lig>>\n"; sub xxxx { ... print STDERR "ligX <<$lig>>\n"; } print STDERR "ligB <<$lig>>\n"; xxxx();
Sometimes I get (not always):
ligA <<4>> ligB <<4>> ligX <<>>
My question is , why $lig is undefined inside xxxx, and al least how can it be corrected ?
Thanks.

Replies are listed 'Best First'.
Re: Basic mod-perl question : why my variable is undefined ?
by kennethk (Abbot) on Jul 23, 2014 at 15:04 UTC

    Are you using warnings? Have you checked your logs? If you are getting a warning like

    Variable "$lig" will not stay shared
    You have scoping problems with your closure. That warning will be issued by code like
    sub one { my $x; sub two { print $x; } }

    Since mod_perl compiles all your scripts into a dispatch table (as I understand it), it seems plausible to me that the copy of $lig referenced in your compiled copy of xxx() is not the lexically-scoped variable you are working with after your script executes a couple times.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Yes you are right, "I" am exactly in this case, as mod_perl includes (automatically) my full script in a sub. So maybe it is my understanding of what is a "closure" or what is "lexically-scoped" which is bad.
      I would have thought that as $x is defined in sub one, its scope goes until the end of sub one. I suppose I am wrong..? Why ? And is there a way to have a variable common to one and two, but declared inside one, as with mod_perl I have no access (at my knowledge) outside one... ?
        The problem with the demo code is that each subroutine is only compiled once. That means that the $x variable in two corresponds to the $x variable in the first call of one. The first instance of $x persists as there is a reference to it stored in two.

        Solutions include explicitly passing the value, forcing recompile each time through using a code reference (sub), swapping $x to a constant... What is the reason you aren't just passing in the value of $lig?


        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Basic mod-perl question : why my variable is undefined ?
by Anonymous Monk on Jul 23, 2014 at 11:00 UTC
      Thenk you,
      1- You give me very muche reading. Thank you. I have read most of that many times and I am lost in it, and this is the reason that I ask.
      2- OK, I know that there are problems with global variable. Sure I can declare $lig in the sub. But my question is generic : why it does not work ?
Re: Basic mod-perl question : why my variable is undefined ?
by AnomalousMonk (Archbishop) on Jul 23, 2014 at 13:51 UTC

    It's easy to manufacture example code that shows something like the behavior you report:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $x; ;; S('A'); ;; $x = 'foo'; ;; S('B'); ;; sub S { print qq{$_[0]: x is }, defined $x ? qq{'$x'} : 'undefined'; +} " A: x is undefined B: x is 'foo'
    This simple example code always produces the output shown. It's easy to imagine that in your "much more complex" code different execution paths are sometimes taken, such that your equivalent of  $x has, on occasion, already been initialized when subroutine  S() is called at point 'A'. In any event, I hope it is clear why  $x is uninitialized at point 'A' and initialized at point 'B'.

    Update: See also the discussion in response to subroutine no error.

      Thank you. This is clear, but it is not my problem. And this is not mod-perl. The point is "sometimes", not "always".
Re: Basic mod-perl question : why my variable is undefined ?
by kcott (Archbishop) on Jul 23, 2014 at 11:33 UTC

    G'day pcouderc,

    I was unable to replicate your results:

    #!/usr/bin/env perl use strict; use warnings; my $lig; #... $lig=4; print STDERR "ligA <<$lig>>\n"; sub xxxx { #... print STDERR "ligX <<$lig>>\n"; } print STDERR "ligB <<$lig>>\n"; xxxx();

    Outputs:

    ligA <<4>> ligB <<4>> ligX <<4>>

    [I'm running 5.18.1 on darwin-thread-multi-2level]

    -- Ken

      Thank you. Did you try under mod-perl ?
      Anyway, my script is much more complex. And sometimes the result is ok. Other times it is not.
Re: Basic mod-perl question : why my variable is undefined ?
by hippo (Archbishop) on Jul 23, 2014 at 12:15 UTC

    Your reported output lgeX <<>> does not match any of the I/O lines in your provided code. Are you perhaps confusing the $lig variable with something else?

    Why is $lig a variable if you never change its value? Why not declare it as a constant instead? If its value does change (from 4) why have you not shown that code?

    Update note: The OP has now removed the reference in the parent node to "lgeX" in the output.

      Thank you. Well, there is no mistake. You see lgeX<<>> because $lig is not correct and seems to be undef. I have simplified the code. In fact $lig is incremented in xxxx().

        Perhaps I have not been clear enough. The string "lgeX" appears in your reported output but does not appear anywhere in your provided code. Can you explain that, please?

Re: Basic mod-perl question : why my variable is undefined ?
by locked_user sundialsvc4 (Abbot) on Jul 23, 2014 at 11:03 UTC

    Well, first of all, the usual questions ... do you have use strict; use warnings; and in that situation does it “compile cleanly?”

    Next, well, there is no such thing as “sometimes, not always.”   What you are dealing with here is a bug ... in your code.   Somewhere.   That bug is probably located in the bit of code that you elided out, the second time, with "...".   I do not believe that this has anything in particular to do either with mod_perl nor the Registry.

    In addition, I suggest that you should put all your code together, in subroutines, and not put subroutines in-the-middle.   Let the code-paths be obvious, and contiguous.

      Thank you. Well, I fear that you answer without knowing mod_perl. I suggest you read that http://perl.apache.org/docs/1.0/guide/porting.html#Exposing_Apache__Registry_secrets