void loader_thread_exit(dcontext_t *dcontext) { privmod_t *mod; /* assuming context swap have happened when entered DR */ if (privload_has_thread_entry() && /* Only call if we're cleaning up the currently executing thread, as * that's what the entry routine is going to do! Calling on other * threads results in problems like double frees (i#969). Exiting * another thread should only happen on process exit or forced thread * termination. The former can technically continue (app could call * NtTerminateProcess(0) but then keep going) but we have never seen * that; and the latter doesn't do full native cleanups anyway. Thus * we're not worried about leaks from not calling DLL_THREAD_EXIT. * (We can't check get_thread_private_dcontext() b/c it's already cleared.) */ dcontext->owning_thread == get_thread_id()) { acquire_recursive_lock(&privload_lock); /* Walk forward and call independent libs last */ for (mod = modlist; mod != NULL; mod = mod->next) { if (!mod->externally_loaded) privload_call_entry(mod, DLL_THREAD_EXIT); } release_recursive_lock(&privload_lock); } /* os specific thread exit for loader, holding no lock */ os_loader_thread_exit(dcontext); }
void loader_thread_exit(dcontext_t *dcontext) { privmod_t *mod; /* assuming context swap have happened when entered DR */ if (privload_has_thread_entry()) { acquire_recursive_lock(&privload_lock); /* Walk forward and call independent libs last */ for (mod = modlist; mod != NULL; mod = mod->next) { if (!mod->externally_loaded) privload_call_entry(mod, DLL_THREAD_EXIT); } release_recursive_lock(&privload_lock); } /* os specific thread exit for loader, holding no lock */ os_loader_thread_exit(dcontext); }
void loader_thread_init(dcontext_t *dcontext) { privmod_t *mod; if (modlist == NULL) { #ifdef WINDOWS /* FIXME i#338: once restore order this will become nop */ /* os specific thread initilization prologue for loader with no lock */ os_loader_thread_init_prologue(dcontext); /* os specific thread initilization epilogue for loader with no lock */ os_loader_thread_init_epilogue(dcontext); #endif /* WINDOWS */ } else { /* os specific thread initilization prologue for loader with no lock */ os_loader_thread_init_prologue(dcontext); if (privload_has_thread_entry()) { /* We rely on lock isolation to prevent deadlock while we're here * holding privload_lock and the priv lib * DllMain may acquire the same lock that another thread acquired * in its app code before requesting a synchall (flush, exit). * FIXME i#875: we do not have ntdll!RtlpFlsLock isolated. * Living w/ it for now. It should be unlikely for the app to * hold RtlpFlsLock and then acquire privload_lock: privload_lock * is used for import redirection but those don't apply within * ntdll. */ ASSERT_OWN_NO_LOCKS(); acquire_recursive_lock(&privload_lock); /* Walk forward and call independent libs last. * We do notify priv libs of client threads. */ for (mod = modlist; mod != NULL; mod = mod->next) { if (!mod->externally_loaded) privload_call_entry(mod, DLL_THREAD_INIT); } release_recursive_lock(&privload_lock); } /* os specific thread initilization epilogue for loader with no lock */ os_loader_thread_init_epilogue(dcontext); } }