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

I have used Super Search to find an answer to this, but haven't found the right answer yet:

I have a Perl script that needs to load a module, foo.pm, which in turn uses XSLoader to load libfoo_perl.so. libfoo_perl.so has a reference to bar.so which is not in a standard path. I can not modify the environment variables before running my script. The script looks like this:

$ENV{PATH} = "/foo/bin:/bar/bin:$ENV{PATH}"; $ENV{LD_LIBRARY_PATH} = "/foo/bin:/bar/bin:$ENV{LD_LIBRARY_PATH}"; $ENV{PERL5LIB} = "/foo/lib:$ENV{PERL5LIB}"; use lib "/foo/lib"; use foo; # if I comment the above line and # uncomment below, it works, but that is not what I want. # print `perl -e 'use foo; print "success\n";'`;
The above would give me an error like this: Can't load '/foo/bin/libfoo_perl.so' for module foo_perl: bar.so: cannot open shared object file: No such file or directory at /auto/perl/5.8.3/lib/5.8.3/i686-linux-thread-multi/DynaLoader.pm line 229.

I know the easy solution is to add the directory for bar.so to LD_LIBRARY_PATH, but I can not do that. I am not allowed to touch the environment outside the script. Only inside the script. And no, I can not recompile libfoo_perl.so to hard code the path to bar.so.

It would appear that the dl_load_file() function in DynaLoader does not inherit the current %ENV settings, and instead uses the parent environment settings.

Using Perl 5.8.3, if you haven't guessed already.

Thanks for the help,
Imran

Replies are listed 'Best First'.
Re: DynaLoader and LD_LIBRARY_PATH
by derby (Abbot) on Nov 10, 2005 at 17:21 UTC

    The classic way to handle this is to have a script (shell mostly but it could be perl) that first sets the environment correctly and then executes the dependent program:

    #!/bin/bash export LD_LIBRARY_PATH=/path/to/foo:$LD_LIBRARY_PATH /path/to/perl/script
    -derby
      I am aware of that solution. The scripts in question have been upgraded to use these modules. The user of the scripts does not want to change his habits when it comes to running the scripts, i.e. run a shell script instead of the perl script directly. To keep it backward compatible, he wants the Perl script to be run directly without any prior modification of the environment.

      -Imran

        So then rename the perl script to script-old, the shell script to the same name as script-old and pass any args along. If your looking for a way to modify your current script to load the proper ld path, you're out of luck

        If you don't like the shell script invocation, you can do as another poster suggested and have your perlscript set-up the environment in a begin block and then re-exec itself

        -derby
Re: DynaLoader and LD_LIBRARY_PATH
by Tanktalus (Canon) on Nov 10, 2005 at 18:06 UTC

    Looks to me like you need to put all those %ENV settings into a BEGIN block where they are (before the "use foo" line). They aren't being set until after "use foo" is finished running (since use is itself an implicit BEGIN block), and that means you're loading your library (or trying to) based on the environment before you change it.

    The alternate idea, if that doesn't work, is to check if %ENV has your settings in it, if it doesn't, just set it, then re-exec yourself. This, too, would need to happen inside a BEGIN block so that you run the exec before you try to "use foo".

      I did try it with a BEGIN block. I took the BEGIN block out in my post. It did not make it work.

      Your alternate idea would be something like this?

      BEGIN { unless ($ENV{PATH} =~ m#/foo/bin#) { $ENV{PATH} = "/foo/bin:/bar/bin:$ENV{PATH}"; $ENV{LD_LIBRARY_PATH} = "/foo/bin:/bar/bin:$ENV{LD_LIBRARY_PATH}"; $ENV{PERL5LIB} = "/foo/lib:$ENV{PERL5LIB}"; exec("$0 @ARGV"); exit; } } use foo;
      ? -Imran

        Close. The exec line would look like this:

        exec($^X, $0, @ARGV);
        And you don't need the exit line - when exec runs, it replaces the current process with the new process. The "current" process won't even exist anymore - processing continues at the beginning of the new program.

Re: DynaLoader and LD_LIBRARY_PATH (link)
by tye (Sage) on Nov 11, 2005 at 03:35 UTC