void WINAPI myThread(void* arg) { int num; num = *((int*) arg); if (TEST_NUM != num) { fprintf(stderr, "myThread: %d expected, but %d received\n", TEST_NUM, num); exit(EXIT_FAILURE); } NaClThreadExit(0); }
void NaClReverseThreadIfExit(struct NaClThreadInterface *vself, void *exit_code) { struct NaClReverseCountingThreadInterface *self = (struct NaClReverseCountingThreadInterface *) vself; NaClLog(4, ("NaClReverseThreadIfExit: thread 0x%"NACL_PRIxPTR " is exiting\n"), (uintptr_t) vself); (*NACL_VTBL(NaClReverseService, self->reverse_service)->ThreadCountDecr)( self->reverse_service); NaClRefCountUnref((struct NaClRefCount *) self); NaClThreadExit((int)(uintptr_t) exit_code); }
void WINAPI serviceThread(void* arg) { struct ServiceThreadArgs* typedArg; NaClSrpcImcDescType desc; NaClSrpcHandlerDesc handlers[] = { { "getNum::i", handleGetNum }, { NULL, NULL } }; typedArg = (struct ServiceThreadArgs*) arg; desc = typedArg->desc; free(typedArg); if (!NaClSrpcServerLoop(desc, handlers, 0)) { failWithErrno("NaClSrpcServerLoop"); exit(EXIT_FAILURE); } #ifdef __native_client__ close(desc); #else NaClDescUnref(desc); #endif NaClThreadExit(0); }
/* * natp should be thread_self(), called while holding no locks. */ void NaClAppThreadTeardown(struct NaClAppThread *natp) { struct NaClApp *nap; size_t thread_idx; /* * mark this thread as dead; doesn't matter if some other thread is * asking us to commit suicide. */ NaClLog(3, "NaClAppThreadTeardown(0x%08"NACL_PRIxPTR")\n", (uintptr_t) natp); nap = natp->nap; if (NULL != nap->debug_stub_callbacks) { NaClLog(3, " notifying the debug stub of the thread exit\n"); /* * This must happen before deallocating the ID natp->thread_num. * We have the invariant that debug stub lock should be acquired before * nap->threads_mu lock. Hence we must not hold threads_mu lock while * calling debug stub hooks. */ nap->debug_stub_callbacks->thread_exit_hook(natp); } NaClLog(3, " getting thread table lock\n"); NaClXMutexLock(&nap->threads_mu); NaClLog(3, " getting thread lock\n"); NaClXMutexLock(&natp->mu); /* * Remove ourselves from the ldt-indexed global tables. The ldt * entry is released as part of NaClAppThreadDelete(), and if * another thread is immediately created (from some other running * thread) we want to be sure that any ldt-based lookups will not * reach this dying thread's data. */ thread_idx = NaClGetThreadIdx(natp); /* * On x86-64 and ARM, clearing nacl_user entry ensures that we will * fault if another syscall is made with this thread_idx. In * particular, thread_idx 0 is never used. */ nacl_user[thread_idx] = NULL; #if NACL_WINDOWS nacl_thread_ids[thread_idx] = 0; #elif NACL_OSX NaClClearMachThreadForThreadIndex(thread_idx); #endif /* * Unset the TLS variable so that if a crash occurs during thread * teardown, the signal handler does not dereference a dangling * NaClAppThread pointer. */ NaClTlsSetCurrentThread(NULL); NaClLog(3, " removing thread from thread table\n"); /* Deallocate the ID natp->thread_num. */ NaClRemoveThreadMu(nap, natp->thread_num); NaClLog(3, " unlocking thread\n"); NaClXMutexUnlock(&natp->mu); NaClLog(3, " unlocking thread table\n"); NaClXMutexUnlock(&nap->threads_mu); NaClLog(3, " unregistering signal stack\n"); NaClSignalStackUnregister(); NaClLog(3, " freeing thread object\n"); NaClAppThreadDelete(natp); NaClLog(3, " NaClThreadExit\n"); NaClThreadExit(); NaClLog(LOG_FATAL, "NaClAppThreadTeardown: NaClThreadExit() should not return\n"); /* NOTREACHED */ }