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

I have a module (specifically, DBD::Oracle) failing to load because the Oracle library (specifically, libclntsh.so.1.0) is not where it expects to find it. Ordinarily, I would simply set LD_LIBRARY_PATH to include the non-standard directory where this library exists, and all would be well. However, changes to this variable within my Perl script (even within a BEGIN block) fail to make any difference at all to the actual search path used by Perl, and this library search doesn't seem to be subject to something controllable like @dl_search_path in DynaLoader (presumably because it's the Oracle.so trying to load the .so, not the Perl module). If I set LD_LIBRARY_PATH variable outside of the Perl script, and then execute it, everything works as it should.

Is there any reason why loading shared libraries would honor an environment variable set before execution of the script as opposed to being set after the script starts executing but before the request for the shared library occurs? Is there any easy way of fixing this in the module that wouldn't involve something at the system-level? The solution I'll end up going with is modifying the user profile to include this Oracle lib directory in LD_LIBRARY_PATH, but I'm wondering why setting this environment variable within Perl would have no effect on the actual library path used.

  • Comment on Setting LD_LIBRARY_PATH for DynaLoader modules

Replies are listed 'Best First'.
(tye)Re: Setting LD_LIBRARY_PATH for DynaLoader modules
by tye (Sage) on Jan 05, 2001 at 02:34 UTC

    See RE: Re: DBI, DBD::Oracle and LD_LIBRARY_PATH for a solution. You have to exec something else to flush ld's cache so that the next exec will look at the new value for LD_LIBRARY_PATH.

    Also, you can perhaps link the extension with LD_RUN_PATH set to tell it where to find the shared libraries so that LD_LIBRARY_PATH will no longer be needed at run time.

    You could also use low-level functions of Perl's DynaLoader to explicitly load the dynamic library before you load the DBI extension.

    This post has been updated.

            - tye (but my friends call me "Tye")
      This last suggestion intrigued me, and I attempted it, but I get relocation errors. Doing a truss on a properly running script yielded no additional shared libraries, so I'm kind of stumped where to proceed next along this line.
      dl_load_file: ld.so.1: /export/home/webadmin/bin/perl: fatal: relocati +on error: file /usr/local/opt/oracle/product/8.0.5/lib/libclntsh.so: +symbol slpmprodstab: referenced symbol not found at VDS/Tests/DB.pm l +ine 29.
      Attempting to load an 8.1.6 version (libclntsh.so.8.0) succeeds, but I guess Oracle.so is still expecting the older version, so I still get the 'open failed' error from install_driver(Oracle)/DynaLoader..

      On a related note, I can't figure out how to get Netscape web server 3.6 to pass this LD_LIBRARY_PATH to CGI scripts! Grr.. (Update: I have since figured this out, so my problem is essentially solved.)

      The exec solution isn't an option here, since this is actually a module and I'd kind of like to keep it transparent to the caller. Is there any way I can modify Oracle.so's RUN_PATH without rebuilding Oracle.so? (We resorted to some serious trickiness to get this to build, since this system doesn't have a fully copy of Oracle installed on it.)

        What you need to do is put it in your /etc/profile directory. This is because the User that runs your CGIs should call this before it runs anything. I added these lines in my /etc/profile to make it work:
        ORACLE_HOME="/usr/local/OraHome1" PATH="$PATH:$ORACLE_HOME/bin:" export ORACLE_HOME export LD_LIBRARY_PATH=$ORACLE_HOME/lib
        It worked fine for me after I did that.

        --BigJoe

        Learn patience, you must.
        Young PerlMonk, craves Not these things.
        Use the source Luke.
Re: Setting LD_LIBRARY_PATH for DynaLoader modules
by chipmunk (Parson) on Jan 05, 2001 at 02:21 UTC
    This behavior of LD_LIBRARY_PATH recently came up on the dbi-users mailing list. Apparently, LD_LIBRARY_PATH has to be set before the process starts. That's just the way it works. I'm not sure why. :/

    My preferred solution is to add the Oracle lib directory to /etc/ld.so.conf and then run ldconfig. That will make the Oracle libraries available to all processes.

      huh. I never thought of telling ldconfig to look in another directory. I always just 'ln'ed a link to the db libs in /usr/local/lib and ran it. =P
      /me makes note of ld.so.conf on hand...

      Come to think of it, most of the time I wanted to add environment variables to root and other stuff so sometimes I just rebooted and tried that new kernel at the same time. The evil influence of Windows, I suppose.

      --
      $you = new YOU;
      honk() if $you->love(perl)