Diddling @INC, order of entries in it

IvorW combobulus at xemaps.com
Wed Aug 1 19:51:18 BST 2007


Adriano Ferreira wrote:
> On 8/1/07, David Cantrell <david at cantrell.org.uk> wrote:
>   
>> [ Adriano Ferreira CCed so he knows just what kind of insanity I'm
>>   inflicting on his code :-) ]
>>
>> I'm hacking around in the guts of Devel::Hide, trying to add a facility
>> to make it hide modules from child processes created by fork-and-exec,
>> so eg ...
>>
>>     use Devel::Hide qw(-fromchildren Foo::Bar);
>>
>>     system("perl -MFoo::Bar ..."); # Foo::Bar is unavailable here
>>
>> D::H works by putting a coderef into @INC, which checks what you're
>> trying to load, and which fails as appropriate.
>>
>> I have it so that if you pass the magic value '-fromchildren' to D::H's
>> import() like above, it puts MDevel::Hide=Foo::Bar into PERL5OPT.  And it
>> works.
>>
>> It works right up until the child process does this ...
>>
>>     use lib 'my/secret/stash/of/modules';
>>     use Foo::Bar;
>>
>> cos then, 'my/secret/stash/of/modules' gets stuffed into @INC *before*
>> the coderef, and so if Foo::Bar can be found under there, it gets
>> loaded.  I don't want this to happen, partly because it makes writing
>> the tests (which start with 'use lib "t"') for the new bits of code in
>> Devel::Hide a bit annoying.
>>     
>
>
>   
>> Can anyone think of a nifty way around this?  The only one I can think
>> of is to have Devel::Hide mess around in the guts of lib.pm and change
>> them so that the reference to Devel::Hide's magic subroutine *always*
>> comes first.
>>     
>
> Once you start playing tricks with "lib", you will be surprised by
> code that does not use "lib" but "@INC" directly, doing only:
>
> BEGIN { push @INC, 'my/private/lib/dir' }
>
> So messing with "lib" would not be enough. I think that playing with a
> tied @INC won't work either, if someone do
>
> BEGIN { @INC = ( 'my/private/lib/dir', @INC ) }
>
> or even worst things.
>
>   
>> If I *do* have to mess around in lib's guts, I imagine what I want to
>> do is replace its import() with one that goes ...
>>
>> sub import {
>>     # call the original import(), save its return value
>>     search @INC and move my magic subroutine to the beginning
>>     # return the original import()'s return value
>> }
>>
>> And indeed *should* I be trying to subvert 'use lib' like this?  I can
>> make the tests pass by putting Mlib=t in the right place in PERL5OPT, of
>> course, so perhaps that's the better choice.
>>     
>
>
> On 8/1/07, Dan Rowles <d.rowles at outcometechnologies.com> wrote:
>   
>> How about you override the require method? Or possibly the "do" method
>> instead?
>>
>> Dan
>>     
>
> I think that may be the way to go. I didn't have thought before of
> overriding "do". Can it be done?
>
>   
An alternative approach, which will take a performance hit, is to use
$DB::single to force single step execution, and check @INC after every
line of code, manipulating the coderef to the front of the array if @INC
has changed.


More information about the london.pm mailing list