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

Hello !

I am working with an existing appliciation (on RedHat EL5) which I would like to extend by an embedded Perl interpreter. To get started, I first successfully created a static library, then a shared one which I linked to a simple C program. Everything works fine until I am trying to load the shared library dynamically. Unfortunately the existing application which I want to extend with the Perl interpreter leaves me the only choice to dynamically load a shared library, so there is no alternative to this approach.

I tried to simplify to a maximum to be able to reproduce the problem. I also tried with different Perl versions (I compiled 5.8.8, 5.8.9, 5.10.0) on different servers, everytime the same issue.

The perl script I am trying to run is "hello.pl".

use strict; use warnings; use IO::Socket; # without this line, no crash ! print "** hello from hello.pl **\n";

The shared library is based on the file 'perlLib.c' which embeds the Perl interpreter:

// perlLib.c #include <EXTERN.h> #include <perl.h> EXTERN_C void xs_init (pTHX); PerlInterpreter *my_perl; void myPerlFunc() { char *largv[] = { "", "-f", "hello.pl", NULL }; int largc=3; my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, xs_init, largc, largv, environ); perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl); }

The test executable is based on perlEmbedDynamic.c

// perlEmbedDynamic.c #include <stdio.h> #include <dlfcn.h> int main(int argc, char **argv) { void *handle; void (*theLibFunction)(); handle = dlopen ("libDynamicPerl.so", RTLD_LAZY); theLibFunction = dlsym(handle, "myPerlFunc"); (*theLibFunction)(); dlclose(handle); return(0); }

Finally to compile and test I use a small shell script

# compTest.sh # generate and compile perxsi.c perl -MExtUtils::Embed -e xsinit -- -o perlxsi.c cc -Wall -fPIC -g -c perlxsi.c `perl -MExtUtils::Embed -e ccopts` # perlLib contains the function myPerlFunc which embeds and runs the i +nterpreter cc -Wall -fPIC -g -c perlLib.c `perl -MExtUtils::Embed -e ccopts` # generate the dynamic libray cc -Wall -shared -Wl,-export-dynamic -o libDynamicPerl.so perlLib.o pe +rlxsi.o `perl -MExtUtils::Embed -e ldopts` # linking of the library cc -Wall -L. -lDynamicPerl perlEmbedDynamic.c -o perlEmbedDynamicLinki +ng # execute with linking, works fine ./perlEmbedDynamicLinking # dynamic loading of the library cc -rdynamic -o perlEmbedDynamicLoading perlEmbedDynamic.c -ldl # execute with dynamic loading, crashes ./perlEmbedDynamicLoading

perlxsi.c is created by the script in the usual way. If the hello.pl scripts does not contain the line "use IO::Socket", there is no crash. I also wonder why linking the shared lib works nicely while loading it crashes (where is the internal difference, once the shared lib becomes active ?). Once this works I would like to extend the embedded Perl, so the IO::Socket was just used as an example to be able to easily reproduce the problem.

Any help would be really appreciated !

thanx, lorius

Replies are listed 'Best First'.
Re: embedding perl in a shared library crashes if shared lib is loaded dynamically
by cdarke (Prior) on Jan 06, 2010 at 13:06 UTC
    What kind of crashes are you experiencing?

    Are you sure the shared object is being loaded? After the dlopen you might want to check the value of the handle, for example:
    if (!handle) { fprintf (stderr, "%s\n", dlerror()); return 1; }
    You probably may wish to check the return value from dlsym as well.

    There might be issues using LAZY (although it works for me), but RTLD_NOW is worth a try.

      thx cdarke, I tried this already before (I removed the testing of the handle in my example to limit the sample files to a strict minimum). I just put it back again for safety, same result.

      Also changing RTLD_LAZY to RTLD_NOW creates no different behaviour (just tried it).

      Loading of the shared lib seems to work correctly as removing the line 'use IO::Socket' from hello.pl and executing ./perlEmbedDynamicLoading generates the expected output '** hello from hello.pl **' (so the loading is ok). But when I put back again the statement "use IO::Socket", ./perlEmbedDynamicLinking works fine (just as runinng "perl hello.pl"), but ./perlEmbedDynamicLoading crashes with the only message "memory Fault".

      when you say "although it works for me", does this mean that you've been able to run the example files without any problem ?

        When I said "works for me" I meant that RTLD_LAZY worked, unfortnately I'm not currently in a position to try your code (maybe tonight). Sorry to have mis-lead you.

        This is pure speculation. The difference with a use statement is that it is executed at compile-time. Could you change the use and require the module after you dynamically loaded your code?

        I also found this Problem with dlopen and shared objects using perl libs, but I don't think it helps much.