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

I have embedded a perl interpreter in my application. I start it up and pass it a boot_Clock XS method for a module I made that calls back into the executable. I shut down perl and then reinitialize it, and redo the XS stuff. But after reinitializing, the first time I call a Clock method, I get a fatal perl error: Undefined subroutine &Clock::ctime called at (eval 37) line 6 during global destruction.

It does work fine if I leave the perl interpreter running and never reinitialize it, but I don't want to do that. The reinitialized interpreter works fine if I never use my XS functions.

I am clueless as to what is going wrong. Pointers appreciated.

UPDATE: I was never able to figure out WHY this was misbehaving, but I made it go away by reorganizing my code. It's definitely just an oddity in object creation order in my application and not an interesting perl question, unfortunately. Sorry to have wasted space.

  • Comment on reinitializing embedded perl interpreter: undefined subrouting called during global destruction
  • Download Code

Replies are listed 'Best First'.
Re: reinitializing embedded perl interpreter: undefined subrouting called during global destruction
by BrowserUk (Patriarch) on Mar 31, 2009 at 01:01 UTC
    But after reinitializing, the first time I call a Clock method,

    Sounds like you are hanging onto some pointers within your application that were produced by the first instantiation of the interpreter, and when you restart the interpreter those pointers are no longer valid.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      The XS code has extern InternalClass* pointers in it that are referenced in XS function bodies:

      extern SomeClass* sc; int blah() CODE: RETVAL = sc->blah(); OUTPUT: RETVAL

      Would perl zero out my sc pointer? I'm sure *I* don't reset it. Other than that I don't have any relevant pointers declared myself.

        Hm. Impossible to say given the sparsity of the information. Two thoughts come to mind which may or may not be relevant on your (unstated) platform:

        1. On windows, DLLs (which is where your XS code lives) tend to get loaded once per application.

          So, if you have any static data (pointers) that get initialised when the module is loaded, with values that derive from the interpreter, they may not get re-initialised when a new interpreter is loaded.

          I've no idea if this is the case with .so's on other platforms.

        2. You mentioned that you get problems when calling methods, but you don't mention (re-)creating the instances on which you are calling those methods.

          If your application code stores any pointers--for example, callback addresses--from the first interpreter and tried to reuse them once you've spawned the second instance, those retained pointers are quite likely to be broken.

        Given the generality of the problem description, the best anyone can offer is generalised possibilities for you to look for.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: reinitializing embedded perl interpreter: undefined subrouting called during global destruction
by afoken (Chancellor) on Mar 30, 2009 at 23:23 UTC

    I think you should show us the relevant parts of your code.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      The perl initialization and shut down are basically straight out of the perlembed man page.

      { const char *args[] = { "", "-ew", "0" }; const char** aargs PERL_UNUSED_DECL = args; static int arg_count = sizeof args / sizeof *args; PERL_SYS_INIT(&arg_count, const_cast<char***>(&aargs)); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, xs_init, arg_count, const_cast<char**>(args), NULL +); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; } { perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

      The XS for the relevant module is in another comment in this thread. The code to load the module is vanilla:

      newXS("boot_Clock", functionPointerToEXTERN_C_boot_Clock, __FILE__); eval_pv("boot_Clock", true);