Thanks for your efforts, Shmuel!

On Mon, Aug 04, 2008 at 08:10:31PM +0300, Shmuel Fomberg wrote:
> >>IANAE, (I am not an expert) but if you say that the main thread returns 
> >>immediately and waiting in a loop for the lib, then you already have one 
> >>thread inside Perl. So the background threads shouldn't call into your 
> >>perl interpreter.
> >
> >If I understand correctly, I have two options then:
> >
> >1. _not_ let the main thread return back from the XS.  That is, I
> >   move the sleep(0) from the perl script into the init() function.
> >   Would that break anything withhin perl?
> 
> For this one you need a real expert. It is possible to call into Perl 
> from an XS sub. but to call into Perl from other threads while it is 
> inside a XS call? I have no idea.

As far as I understand the corresponding section in perlguts, it should
be possible _if_ PERL_SET_CONTEXT() is called before.  But for some
reason it keeps crashing :-(

> >2. I need to create a second perl interpreter (or clone the first one).
> >   Can somebody point me to example code how to do that?
> 
> That's actually no big deal. look at perldoc page perlembed, there are 
> examples.

What I am missing from those examples is the explanation how the
different interpreters would communicate.

And there's one more complication: the low-level library don't even
state how many threads will call my callback.  Therefore I would
prefer to have only _one_ interpreter and use a mutex to keep the
threads from entering the interpreter simultaneously.

This is how my code (still crashing) looks right now:



# define PERL_NO_GET_CONTEXT
# include "defs.h"

static SV *callback_ref = (SV*)NULL;

static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

/* This function works OK when called from module_config() in main thread,
   but it crashes on PUSHMARK(SP) when called from other threads
*/
int call_perl (int cnt, ...)
{
    dTHX;
    dSP;

    int i;
    I32 numargs;
    va_list args;

    pthread_mutex_lock(&mutex);

    PERL_SET_CONTEXT(my_perl);

    ENTER;
    SAVETMPS;

    PUSHMARK(SP);  /* Here it crashes when called from different thread */

    va_start (args, cnt);
    while (cnt-- > 0) {
        char *str = va_arg(args, char*);
        XPUSHs(sv_2mortal (newSVpv (str, strlen (str))));
    }
    va_end (args);

    PUTBACK;

    numargs = call_sv (callback_ref, G_SCALAR);

    if (numargs != 1)
        croak("Big trouble\n");

    SPAGAIN;

    for (i=0; i<numargs; i++) {
        printf ("ret %i\n", POPi);
    }

    PUTBACK;
    FREETMPS;
    LEAVE;

    pthread_mutex_unlock(&mutex);

    return numargs;
}

void module_config (SV *callback)
{
    dTHX;

    if (callback_ref == (SV*)NULL) {
        callback_ref = newSVsv (callback); /* first time, create new SV */
    } else {
        SvSetSV (callback_ref, callback);  /* been here, overwrite */
    }

    start_threads ();

    do {
        sleep (180);
    } while (call_perl (1, "check"));  /* works OK when called from here */
}

Reply via email to