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 */
}