You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Christiaan Kras <c....@pcc-online.net> on 2007/07/06 22:57:56 UTC

mod_perl lazy loading modules with eval in custom lib

Hi,

My webhost allows me to use mod_perl (Apache 2 server by the way, Fedora 
distro). And I'm glad I can because it speeds up my perl scripts a lot.
   
I've created a website that's based on CGI::Application, 
Template-Toolkit and DBIx::Class. All works fine.
Those modules, including my own, are in a custom lib. Done so with use 
lib qw(etc etc etc) and just to be sure I've set PERL5LIB.
I've been running it under ModPerl::Registry and ModPerl::PerlRun. Both 
give me the same, infrequent errors.

Modules like Template::Plugins use lazy loading. I load 
Template::Plugin::Date by default (TT is in my custom lib).
The lazy loading happens with a require in an eval block. But somehow, 
my @INC has been reset when going through that eval() part.
Same thing happens with Excel::Template. This modules does the same, but 
in BEGIN blocks.

My scripts don't die. The eval() parts sometimes fail (because it can't 
find the modules). But the rest keeps on working.
I've tried lots of things and have searched all over internet. But I 
can't find a solution. I have no access to httpd.conf so I can't set my 
custom lib at server startup

The problem only happens when a module is loaded in an eval(). Somehow 
my @INC is getting reset. And I don't want that to happen :-)

I've searched perl.apache.org and searched all over internet to find a 
solution. But I couldn't find any.

I'm 100% sure it happens in the modules that use lazy loading 
(eval(require "module.pm")). Somehow @INC gets reset. My errorlog then 
states it can't find the required module. Weird thing is, it happens 
infrequently.

Anyone that had a similar problem and found a solution? Thanks in 
advance :-)

-- 

Christiaan Kras



Re: mod_perl lazy loading modules with eval in custom lib

Posted by Christiaan Kras <c....@pcc-online.net>.
Perrin Harkins schreef:
> On 7/11/07, Christiaan Kras <c....@pcc-online.net> wrote:
>> By the way, I've used push() to add my path to @INC before. But that
>> didn't work out.
>
> It should work fine.  The reason people typically use unshift for this
> is that it lets modules in your local path override ones in the system
> path.
>
> - Perrin
>

I see. Well, it still seems to work but I'll get back to the list if it 
isn't. Although I'm sure now all is well.

-- 


Christiaan Kras



Re: mod_perl lazy loading modules with eval in custom lib

Posted by Perrin Harkins <pe...@elem.com>.
On 7/11/07, Christiaan Kras <c....@pcc-online.net> wrote:
> By the way, I've used push() to add my path to @INC before. But that
> didn't work out.

It should work fine.  The reason people typically use unshift for this
is that it lets modules in your local path override ones in the system
path.

- Perrin

Re: mod_perl lazy loading modules with eval in custom lib

Posted by Christiaan Kras <c....@pcc-online.net>.
Perrin Harkins schreef:
> On 7/11/07, Christiaan Kras <c....@pcc-online.net> wrote:
>> Thanks. I will try that. So basicly, the modules that are loaded at the
>> first request will stay in memory, but @INC will get reset?
>
> Yes.  It's a simulation of CGI behavior.  The only reason your CGI
> scripts don't have this problem is that they execute the "use lib" on
> every request, since they are compiling from scratch every time.
>
I've read about it. I was sure I checked it.
>> Wow. I never noticed it. In my app I have runmode that shows me %ENV and
>> @INC. At the first request my custom path was in there. And at the
>> second request it wasn't. But after a few more requests it's still
>> there. Weird behaviour?
>
> You're probably just seeing a new child process compile the script for
> the first time.
>
>> Just a quick note: unshift removes the first record from the array.
>
> No, it adds to the beginning of the array.
>
> - Perrin
>
Oops, my bad. *ashamed*


Anyway. I've tested it, and now in the runmode that show's me @INC it 
keeps the path I've set. I've tried a number of Excel exports as well 
and none of them were faulty. However, I will keep a look at my logfile. 
But I hope this solves the problem.

By the way, I've used push() to add my path to @INC before. But that 
didn't work out. Was that because push() puts the path at the end of 
@INC? Shouldn't really matter should it? Although it's possible I used 
it after loading my modules (not in the startup sub).

For now I seem to be helped. Thanks again :-).

-- 


Christiaan Kras



Re: mod_perl lazy loading modules with eval in custom lib

Posted by Perrin Harkins <pe...@elem.com>.
On 7/11/07, Christiaan Kras <c....@pcc-online.net> wrote:
> Thanks. I will try that. So basicly, the modules that are loaded at the
> first request will stay in memory, but @INC will get reset?

Yes.  It's a simulation of CGI behavior.  The only reason your CGI
scripts don't have this problem is that they execute the "use lib" on
every request, since they are compiling from scratch every time.

> Wow. I never noticed it. In my app I have runmode that shows me %ENV and
> @INC. At the first request my custom path was in there. And at the
> second request it wasn't. But after a few more requests it's still
> there. Weird behaviour?

You're probably just seeing a new child process compile the script for
the first time.

> Just a quick note: unshift removes the first record from the array.

No, it adds to the beginning of the array.

- Perrin

Re: mod_perl lazy loading modules with eval in custom lib

Posted by Clinton Gormley <cl...@traveljury.com>.
> Wow. I never noticed it. In my app I have runmode that shows me %ENV and 
> @INC. At the first request my custom path was in there. And at the 
> second request it wasn't. But after a few more requests it's still 
> there. Weird behaviour?

All that means is that you're hitting a new child for the first time.

> 
> Anyway, thanks. I'll try it later on. I'll post again if it doesn't help.
> 
> Just a quick note: unshift removes the first record from the array. But 
> what if my path isn't in @INC at a second request. That would remove a 
> normal path that's always around wouldn't it? Guess I'll just have to 
> try and see :-). Thanks.

You're thinking of shift :)

unshift is the opposite - it adds the new path onto the front of @INC.

Clint
> 


Re: mod_perl lazy loading modules with eval in custom lib

Posted by Christiaan Kras <c....@pcc-online.net>.
Perrin Harkins schreef:
> On 7/11/07, Christiaan Kras <c....@pcc-online.net> wrote:
>> I add to @INC with " use lib qw(/my/path) ". All the other modules I
>> load continue to work fine. Just those that use lazy loading fail
>> infrequently.
>
> Okay, I think I see the problem.  When you change @INC during a
> request, the change only lasts for the length of that one request:
> http://perl.apache.org/docs/2.0/user/coding/coding.html#Request_localized_Globals 
>
>
> Because you do a "use lib", @INC is only set the first time you run
> this script.  Change it to this:
> unshift @INC, qw(/my/path/);
>
> - Perrin
>
Thanks. I will try that. So basicly, the modules that are loaded at the 
first request will stay in memory, but @INC will get reset?

...testing...

Wow. I never noticed it. In my app I have runmode that shows me %ENV and 
@INC. At the first request my custom path was in there. And at the 
second request it wasn't. But after a few more requests it's still 
there. Weird behaviour?

Anyway, thanks. I'll try it later on. I'll post again if it doesn't help.

Just a quick note: unshift removes the first record from the array. But 
what if my path isn't in @INC at a second request. That would remove a 
normal path that's always around wouldn't it? Guess I'll just have to 
try and see :-). Thanks.

-- 

Christiaan Kras




Re: mod_perl lazy loading modules with eval in custom lib

Posted by Perrin Harkins <pe...@elem.com>.
On 7/11/07, Christiaan Kras <c....@pcc-online.net> wrote:
> I add to @INC with " use lib qw(/my/path) ". All the other modules I
> load continue to work fine. Just those that use lazy loading fail
> infrequently.

Okay, I think I see the problem.  When you change @INC during a
request, the change only lasts for the length of that one request:
http://perl.apache.org/docs/2.0/user/coding/coding.html#Request_localized_Globals

Because you do a "use lib", @INC is only set the first time you run
this script.  Change it to this:
unshift @INC, qw(/my/path/);

- Perrin

Re: mod_perl lazy loading modules with eval in custom lib

Posted by Christiaan Kras <c....@pcc-online.net>.
Perrin Harkins schreef:
> On 7/7/07, Christiaan Kras <c....@pcc-online.net> wrote:
>> Because in my error messages it clearly says it can't find the modules
>> in @INC. Then it shows all the paths in @INC and my custom lib isn't set
>> there, instead, @INC is at it's original state.
>
> Okay, you said you don't add to @INC at startup.  How do you adjust
> @INC?  Is it possible you have a code path that doesn't set @INC?  Is
> it possible that some of your code is still running under CGI?
>
> - Perrin
>
I add to @INC with " use lib qw(/my/path) ". All the other modules I 
load continue to work fine. Just those that use lazy loading fail 
infrequently.
I've build it in a way that it will run under CGI as well as mod-perl 
(using perl-script handler). For a temporary solution I've added a CGI 
script that's exactly the same as the perl script, but run under CGI, to 
generate my Excel files without error. Not a very comforting solution, 
but for now it works. Although I would love to know the real solution.

Thanks.


-- 
Christiaan Kras




Re: mod_perl lazy loading modules with eval in custom lib

Posted by Perrin Harkins <pe...@elem.com>.
On 7/7/07, Christiaan Kras <c....@pcc-online.net> wrote:
> Because in my error messages it clearly says it can't find the modules
> in @INC. Then it shows all the paths in @INC and my custom lib isn't set
> there, instead, @INC is at it's original state.

Okay, you said you don't add to @INC at startup.  How do you adjust
@INC?  Is it possible you have a code path that doesn't set @INC?  Is
it possible that some of your code is still running under CGI?

- Perrin

Re: mod_perl lazy loading modules with eval in custom lib

Posted by Christiaan Kras <c....@pcc-online.net>.
Yes,

Because in my error messages it clearly says it can't find the modules 
in @INC. Then it shows all the paths in @INC and my custom lib isn't set 
there, instead, @INC is at it's original state.

Christiaan Kras

Perrin Harkins schreef:
> On 7/6/07, Christiaan Kras <c....@pcc-online.net> wrote:
>> I'm 100% sure it happens in the modules that use lazy loading
>> (eval(require "module.pm")). Somehow @INC gets reset.
>
> Are you sure @INC is getting reset?  Sometimes people have this
> problem because the user that apache runs as (usually "nobody")
> doesn't have permissions to access the directories in @INC.  At
> startup, they get loaded as root, so this isn't an issue at that time.
>
> - Perrin
>



Re: mod_perl lazy loading modules with eval in custom lib

Posted by Perrin Harkins <pe...@elem.com>.
On 7/6/07, Christiaan Kras <c....@pcc-online.net> wrote:
> I'm 100% sure it happens in the modules that use lazy loading
> (eval(require "module.pm")). Somehow @INC gets reset.

Are you sure @INC is getting reset?  Sometimes people have this
problem because the user that apache runs as (usually "nobody")
doesn't have permissions to access the directories in @INC.  At
startup, they get loaded as root, so this isn't an issue at that time.

- Perrin