int NaClWaitForMainThreadToExit(struct NaClApp *nap) { NaClLog(3, "NaClWaitForMainThreadToExit: taking NaClApp lock\n"); NaClXMutexLock(&nap->mu); NaClLog(3, " waiting for exit status\n"); while (nap->running) { NaClXCondVarWait(&nap->cv, &nap->mu); NaClLog(3, " wakeup, nap->running %d, nap->exit_status %d\n", nap->running, nap->exit_status); } NaClXMutexUnlock(&nap->mu); /* * Some thread invoked the exit (exit_group) syscall. */ if (NULL != nap->debug_stub_callbacks) { nap->debug_stub_callbacks->process_exit_hook(); } return NACL_ABI_WEXITSTATUS(nap->exit_status); }
int NaClReportExitStatus(struct NaClApp *nap, int exit_status) { int rv = 0; NaClSrpcError rpc_result; NaClXMutexLock(&nap->mu); /* * If several threads are exiting/reporting signals at once, we should * let only one thread to pass through. This way we can use exit code * without synchronization once we know that running==0. */ if (!nap->running) { NaClXMutexUnlock(&nap->mu); return 0; } if (NACL_REVERSE_CHANNEL_INITIALIZED == nap->reverse_channel_initialization_state) { /* TODO(halyavin) update NaCl plugin to accept full exit_status value */ if (NACL_ABI_WIFEXITED(exit_status)) { rpc_result = NaClSrpcInvokeBySignature(&nap->reverse_channel, NACL_REVERSE_CONTROL_REPORT_STATUS, NACL_ABI_WEXITSTATUS(exit_status)); rv = NACL_SRPC_RESULT_OK == rpc_result; } /* * Due to cross-repository checkins, the Cr-side might not yet * implement this RPC. We return whether shutdown was reported. */ } nap->exit_status = exit_status; nap->running = 0; NaClXCondVarSignal(&nap->cv); NaClXMutexUnlock(&nap->mu); return rv; }