in reply to Re^3: Multiple perl interpreters and Module::Runtime (&)
in thread Multiple perl interpreters and Module::Runtime

How does it crash?
Sorry, I should have been more specific.

The program crashes with SEGFAULT after executing this line (, line 64):

64: *{"$callpkg\::$_"} = \&{"$pkg\::$_"} foreach @_;

\&... would never do what &... does. \&... takes a reference to a subroutine while &... invokes a subroutine. So what &{"$pkg\::$_"} does is rather irrelevant. It is indeed unfortunate that Params::Classify::is_string() stupidly produces an endless recursive loop when not given any parameters. But that likely has nothing to do with your original problem.

Indeed, you are right. However the expression \&{"$pkg\::$_"} entered into the perl debugger yields the same result - SEGFAULT crash.

I've been trying to find the part of the line 64 that causes problems - and it shows that the bad part is the expression \&{"$pkg\::$_"}. Perl somehow cannot correctly resolve the function Params::Classify::is_string.

My previous post followed with a GDB backtrace generated from the core dump of the crashed program. It shows where exactly the segfaulted.

Btw. have you tried that program? Does it work on your computer?

Replies are listed 'Best First'.
Re^5: Multiple perl interpreters and Module::Runtime (XS--)
by tye (Sage) on Feb 08, 2011 at 15:02 UTC

    I'm not surprised that Params::Classify fails when used more than once in the same process.

    Here it declares a single data structure per process:

    static struct rtype_metadata { char const *desc_noun, *keyword_pv; SV *keyword_sv; } rtype_metadata[RTYPE_COUNT] = { { "scalar", "SCALAR", NULL }, { "array", "ARRAY", NULL }, { "hash", "HASH", NULL }, { "code", "CODE", NULL }, { "format", "FORMAT", NULL }, { "io", "IO", NULL }, };

    That data structure will eventually contain pointers to Perl variables, as set here:

    rtypemeta->keyword_sv = newSVpvn_share(rtypemeta->keyword_pv, strlen(rtypemeta->keyword_pv), 0);

    I don't believe that you can safely use Perl variables from one interpreter instance in a different instance of the interpreter.

    You could try loading Params::Classify in multiple Perl "threads" (using and see if that also dies and file a bug against the module.

    Or you could just get similar functionality in a way that doesn't require such a large chunk of XS code (since XS code is, by far, the single biggest source of core dumps in Perl -- because it is extremely hard to write robust XS code), especially XS code that entwines itself into everything by hooking 'entersub' and doing manipulations of the Perl opcodes.

    When searching the module documentation for some hint of why it hooked 'entersub' and manipulated opcodes, I found none, but I did find:

    This module is implemented in XS, with a pure Perl backup version for systems that can't handle XS.

    So, if you really want Params::Classify features, you could use the non-XS implementation (you'll have to figure out how that is done).

    Btw. have you tried that program?

    No. I have no intention of even downloading Param::Classify, much less trying to reproduce your problem locally.

    - tye        

      I'm the author of Params::Classify. <> has drawn my attention to this thread, after reporting the problem as #72743.

      You're entirely correct that the Params::Classify XS is not thread safe. Until now I haven't bothered with the complication of making any of my modules thread safe, because it seemed that no one was using threads (or at least no one was using my modules with threads). This is the first bug report I've had about thread safety, and shows that I do after all need to put some work into it. I guess other people adopting Module::Runtime, after the eval/require scare earlier this year, has led to Params::Classify suddenly being used far more widely than it was previously.

      The reason why Params::Classify hooks entersub op checking is so that it can compile calls to its functions (at least in the simple cases) down to custom ops. This avoids the rather large function call overhead, which is significant for functions as small as most of P:C's are. Last year I added the custom op code as a result of profiling my employer's code base, which uses P:C extensively in its type system and for parameter checking. The P:C functions were very hot, and the custom ops made a big difference.

      In the next version I expect to replace the manual entersub hooking with use of the new cv_set_call_checker API (via Devel::CallChecker for backwards compatibility). This is an API that I got added to the core because I've ended up doing the entersub dance many times. Usually I use custom ops for semantic reasons, where I have an operation that doesn't really fit as a callable function. Params::Classify is the only place so far that I've used custom ops for performance.

      Thank you, it seems you have found the source of the problem.

      The .pm version of Params::Classify the docs are talking about is right beside the .xs module in the source archive.

      If I edit the .pm module and comment-out the lines:

      eval { local $SIG{__DIE__}; require XSLoader; XSLoader::load(__PACKAGE__, $VERSION); };
      everything works correctly.