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

Hi, monks!
I have error in code when I mix XS(with callbacks) and threads. Simple code to demonstrate (it works fine without threads):
Callback.xs
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" CV* callback_ref; int runCallback(const char* param) { int count; int answer; dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(param, 0))); PUTBACK; count = call_sv((SV*)callback_ref, G_SCALAR); SPAGAIN; if (count != 1) croak("Uncknown return value format. Returned %d params instid 1", + count); answer = POPi; FREETMPS; LEAVE; return answer; } MODULE = Callback PACKAGE = Callback void registCallback(cb) CV* cb; PROTOTYPE: $ PPCODE: callback_ref = cb; void runCallback(param) const char* param; PROTOTYPE: $ PPCODE: XPUSHs(sv_2mortal( newSViv(runCallback(param)) ));

Callback.pm
package Callback; use 5.010000; use threads; use threads::shared; use strict; use warnings; require Exporter; use AutoLoader qw(AUTOLOAD); our @ISA = qw(Exporter); our $VERSION = '0.01'; require XSLoader; XSLoader::load('Callback', $VERSION); sub new { my $invocant = shift; my $callback_ref = shift; $invocant = ref $invocant if ref $invocant; registCallback($callback_ref); my $self = &share({}); return bless $self, $invocant; } sub run { my $self = shift; my $param = shift; runCallback($param); } 1;

test.pl
#!/usr/bin/env perl use strict; use lib qw(./Callback/build/lib/perl5/i386-linux-thread-multi/); use threads; use threads::shared; use Data::Dumper; use Callback; use constant MESSAGE => "Hellow world!!!\n"; my $obj = new Callback (\&printHellow); my $thread = threads->create(sub {$obj->run(&MESSAGE)}) or exit(1); $thread->join(); sub printHellow { my $message = shift; print "MESSAGE: $message\n"; }

OUTPUT:
MESSAGE:
panic: free from wrong pool during global destruction.

Replies are listed 'Best First'.
Re: xs, threads and panic
by BrowserUk (Patriarch) on May 20, 2009 at 07:48 UTC

    I've encountered similar problems trying to use callbacks from XS & Inline::C with 5.10. Code that worked at 5.8.x (with and without threads).

    I suspect, but cannot definitively prove, that when the internal structures were revamped circa 5,9.something to reduce memory consumption, one or more of the macros involved in performing callbacks were not updated (correctly) and the testing slipped through the cracks.

    Try running your code under 5.8.8 (or earlier) and see if that makes the problem 'go away'. If so, you may have a test case simple enough that p5p will accept it as a demonstration of real internals error rather than decrying it as user error; too verbose; wrong platform; or some other excuse for ignoring it.


    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.
      Thanks, BrowserUk, for answer!
      I have installed perl5.8.9 (pervious stable version) and error has gone away. It is cool, but script does not work correctly, it does not print "MESSAGE: Hellow world!!!". And I steel don't know, why =\
      Note, if we remove threads from code:
      change
      my $thread = threads->create(sub {$obj->run(&MESSAGE)}) or exit(1); $thread->join();
      to
      my $callback = sub {$obj->run(&MESSAGE)}; $callback->();
      It works fine.

        Okay. So you are trying to bypass the check that prevent you from passing a reference to a subroutine, by calling into XS and creating an oblique code reference and passing that between threads; and then complaining that it crashes when you bypass the mechanism put in place to prevent you from doing that.

        That's cool. WAD. Working as designed. You reach behind the fireguard and get burned.


        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: xs, threads and panic
by dave_the_m (Monsignor) on May 20, 2009 at 09:57 UTC
    You're sharing a CV between two threads, which is a big no no.

    Dave.

      And? I don't understand you, Dave.
        The way perl's threading model works is that each thread has its own interpreter, and own set of SVs. When a new thread is created, perl makes a copy of every SV it knows about, and 'gives' them to the new interpreter. The new interpreter should not be able to mess with any of the SVs belonging to another interpreter; this is not thread-safe, and crashes and panics will occur.

        What you need to do is replace the callback_ref variable - which perl doesn't know about - with a perl scalar (or array if you need more than one value) that is embedded in a namespace: $Callback::callback_ref, say. Then when you create a thread, a copy of $Callback::callback_ref is made in the new thread, and everyone's happy.

        Dave.

Re: xs, threads and panic
by Cuba (Initiate) on May 20, 2009 at 18:29 UTC
    Ok. Last solution works, but it is not very useful for me. Because, I call callbacks from Perl in my examples. I need pass callbacks to shared library and before creation of threads.

    Is it possible?