static void* run_thread(void* arg) { mthread* thread = (mthread*) arg; PerlInterpreter* my_perl = construct_perl(); const message *to_run, *modules, *message; SV *call, *status; perl_mutex* shutdown_mutex; thread->interp = my_perl; #ifndef WIN32 S_set_sigmask(&thread->initial_sigmask); #endif PERL_SET_CONTEXT(my_perl); store_self(my_perl, thread); { dSP; modules = queue_dequeue(thread->queue, NULL); load_modules(my_perl, modules); to_run = queue_dequeue(thread->queue, NULL); ENTER; SAVETMPS; call = SvRV(message_load_value(to_run)); PUSHMARK(SP); mXPUSHs(newSVpvn("exit", 4)); status = newSVpvn("normal", 6); mXPUSHs(status); mXPUSHs(newSViv(thread->id)); ENTER; PUSHMARK(SP); PUTBACK; call_sv(call, G_SCALAR|G_EVAL); SPAGAIN; if (SvTRUE(ERRSV)) { sv_setpvn(status, "error", 5); warn("Thread %"UVuf" got error %s\n", thread->id, SvPV_nolen(ERRSV)); PUSHs(ERRSV); } message_from_stack_pushed(message); LEAVE; send_listeners(thread, message); destroy_message(message); FREETMPS; LEAVE; } shutdown_mutex = get_shutdown_mutex(); MUTEX_LOCK(shutdown_mutex); perl_destruct(my_perl); MUTEX_UNLOCK(shutdown_mutex); mthread_destroy(thread); PerlMemShared_free(thread); perl_free(my_perl); return NULL; }
/* * Clear up after thread is done with */ void Perl_ithread_destruct (pTHX_ ithread* thread, const char *why) { PerlInterpreter *freeperl = NULL; MUTEX_LOCK(&thread->mutex); if (!thread->next) { Perl_croak(aTHX_ "panic: destruct destroyed thread %p (%s)",thread, why); } if (thread->count != 0) { MUTEX_UNLOCK(&thread->mutex); return; } MUTEX_LOCK(&create_destruct_mutex); /* Remove from circular list of threads */ if (thread->next == thread) { /* last one should never get here ? */ threads = NULL; } else { thread->next->prev = thread->prev; thread->prev->next = thread->next; if (threads == thread) { threads = thread->next; } thread->next = NULL; thread->prev = NULL; } known_threads--; assert( known_threads >= 0 ); #if 0 Perl_warn(aTHX_ "destruct %d @ %p by %p now %d", thread->tid,thread->interp,aTHX, known_threads); #endif MUTEX_UNLOCK(&create_destruct_mutex); /* Thread is now disowned */ if(thread->interp) { dTHXa(thread->interp); ithread* current_thread; #ifdef OEMVS void *ptr; #endif PERL_SET_CONTEXT(thread->interp); current_thread = Perl_ithread_get(aTHX); Perl_ithread_set(aTHX_ thread); SvREFCNT_dec(thread->params); thread->params = Nullsv; perl_destruct(thread->interp); freeperl = thread->interp; thread->interp = NULL; } MUTEX_UNLOCK(&thread->mutex); MUTEX_DESTROY(&thread->mutex); #ifdef WIN32 if (thread->handle) CloseHandle(thread->handle); thread->handle = 0; #endif PerlMemShared_free(thread); if (freeperl) perl_free(freeperl); PERL_SET_CONTEXT(aTHX); }