I'm trying to embed a persistent Perl interpreter into a multithreaded C++
program.  I took a crack at one interpreter per thread (as per perlembed), but
couldn't get it to run (did get it to compile mind you).  In the spirit of
TMTOWTDI, I am trying a "simpler" alternative, sharing a persistent interpreter
across multiple threads, like so:

PerlWrapper.cpp (pseudo code):

static PerlInterpreter* my_perl = NULL;
static Mutex mutex;

class PerlWrapper
{
  PerlWrapper()
  {
    mutex.acquire();
    if ( my_perl == NULL )
    {
      my_perl = perl_alloc();
      perl_construct, parse, etc. etc.
    }
    mutex.release();
  }

  Execute( char* perlFunction, char* args[] )
  {
    mutex.acquire();
    dSP;
    ENTER;
    SAVETMPS;
    PUSHMARK( SP );
    for( int i = 0; args[i] != NULL; i++ )
    {
      XPUSHS( sv_2mortal( newSVpv( args[i], 0 ) ) );
    }
    PUTBACK;
    call_pv( perlFunction, G_SCALAR | G_EVAL );
    SPAGAIN;
    cout << POPp << endl;
    PUTBACK;
    FREETMPS;
    LEAVE;
    mutex.release();
  }
}


This is all going on with "Perl v5.6.0 built for MSWin32-x86-multi-thread"
(built from source, from perl.org, not Activstate) on Windows NT 4.

In the main thread, multiple instances of the PerlWrapper class work fine. 
However, if I create a new thread which instantiates a PerlWrapper, all
instances of PerlWrapper outside of that thread throw access violation
exceptions in Perl56.dll when calling Execute.  Depending on whether or not
there is anything in args, the crash happens in newSVpv or call_pv respectively.

I have tried various permutations, the consistent result being that once an
instance has been created in another thread, everything else breaks.  i.e.

Scenario 1

main    : create a couple of instances
main    : use them
main    : create thread-1
thread-1: create an instance
thread-1: use it
main    : create thread-2
thread-2: create an instance
thread-2: use it - CRASH!


Scenario 2

main    : create thread-1
thread-1: create an instance
thread-1: use it
main    : create thread-2
thread-2: create an instance
thread-2: use it - CRASH!


Scenario 3

main    : create thread-1
thread-1: create an instance
thread-1: use it
main    : create an instance
main    : use it - CRASH!


My hope in writing the PerlWrapper class was to avoid multithread issues in the
Perl56.dll itself.  By manually ensuring that the single Perl interpreter was
ever only servicing a single thread, I hoped to have avoided such
complications.  In seems I haven't - I compiled Perl with USE_MULTI USE_ITHREADS
and USE_IMP_SYS in win32/Makefile.

Can anyone offer any suggestions on what's gone wrong here, and how I might fix
it?

Thanks,

Neil.

Reply via email to