Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { CRASH_COND(p_domain == NULL); String domain_name = mono_domain_get_friendly_name(p_domain); print_verbose("Mono: Unloading domain `" + domain_name + "`..."); if (mono_domain_get() != root_domain) mono_domain_set(root_domain, true); mono_gc_collect(mono_gc_max_generation()); mono_domain_finalize(p_domain, 2000); mono_gc_collect(mono_gc_max_generation()); _domain_assemblies_cleanup(mono_domain_get_id(p_domain)); MonoException *exc = NULL; mono_domain_try_unload(p_domain, (MonoObject **)&exc); if (exc) { ERR_PRINTS("Exception thrown when unloading domain `" + domain_name + "`"); GDMonoUtils::debug_unhandled_exception(exc); return FAILED; } return OK; }
int main() { #if LOADDYNAMIC SetupMono(); #endif #if WIN32 SetEnvironmentVariable(L"MONO_PATH",L"..\\..\\..\\builds\\monodistribution\\lib\\mono\\2.0"); #else setenv("MONO_PATH","../../../builds/monodistribution/lib/mono/2.0",1); #endif MonoDomain* domain = mono_jit_init_version ("Unity Root Domain","v2.0.50727"); //create and set child domain MonoDomain* child = mono_domain_create_appdomain("Unity Child Domain",NULL); mono_domain_set(child,0); //load assembly and call entrypoint MonoAssembly* ass = mono_domain_assembly_open (mono_domain_get (),"lucas.exe"); MonoImage* img = mono_assembly_get_image(ass); printf("image %p\n",img); MonoMethodDesc* desc = mono_method_desc_new("Main2:Main",1); MonoMethod* m = mono_method_desc_search_in_image(desc,img); printf("method %p\n",m); MonoObject* exc; MonoObject* newinst = mono_object_new(mono_domain_get(),mono_method_get_class(m)); MonoObject* ret = mono_runtime_invoke(m,newinst,0,&exc); printf ("Exception: %p\n",exc); if (exc) { MonoException* exc2 = (MonoException*) exc; printf ("exc msg:%s\n",mono_class_get_name(mono_object_get_class((MonoObject*)exc))); } printf ("ret: %p\n",ret); Sleep(0); //switch back to root domain mono_domain_set(domain,0); mono_domain_unload(child); mono_runtime_set_shutting_down (); mono_threads_set_shutting_down (); mono_thread_pool_cleanup (); mono_domain_finalize(mono_get_root_domain(),2000); mono_runtime_cleanup(mono_get_root_domain()); printf("Unloading mono\n"); #if LOADDYNAMIC CleanupMono(); #endif while(1){} //sleep so stale monothreads have a chance to crash return 0; }
Error GDMono::_unload_scripts_domain() { ERR_FAIL_NULL_V(scripts_domain, ERR_BUG); if (OS::get_singleton()->is_stdout_verbose()) { OS::get_singleton()->print("Mono: Unloading scripts domain...\n"); } _GodotSharp::get_singleton()->_dispose_callback(); if (mono_domain_get() != root_domain) mono_domain_set(root_domain, true); mono_gc_collect(mono_gc_max_generation()); finalizing_scripts_domain = true; mono_domain_finalize(scripts_domain, 2000); finalizing_scripts_domain = false; mono_gc_collect(mono_gc_max_generation()); _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain)); api_assembly = NULL; project_assembly = NULL; #ifdef TOOLS_ENABLED editor_api_assembly = NULL; #endif MonoDomain *domain = scripts_domain; scripts_domain = NULL; _GodotSharp::get_singleton()->_dispose_callback(); MonoObject *ex = NULL; mono_domain_try_unload(domain, &ex); if (ex) { ERR_PRINT("Exception thrown when unloading scripts domain:"); mono_print_unhandled_exception(ex); return FAILED; } return OK; }
Error GDMono::_unload_scripts_domain() { ERR_FAIL_NULL_V(scripts_domain, ERR_BUG); print_verbose("Mono: Unloading scripts domain..."); _GodotSharp::get_singleton()->_dispose_callback(); if (mono_domain_get() != root_domain) mono_domain_set(root_domain, true); mono_gc_collect(mono_gc_max_generation()); mono_domain_finalize(scripts_domain, 2000); mono_gc_collect(mono_gc_max_generation()); _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain)); core_api_assembly = NULL; project_assembly = NULL; #ifdef TOOLS_ENABLED editor_api_assembly = NULL; #endif core_api_assembly_out_of_sync = false; editor_api_assembly_out_of_sync = false; MonoDomain *domain = scripts_domain; scripts_domain = NULL; _GodotSharp::get_singleton()->_dispose_callback(); MonoException *exc = NULL; mono_domain_try_unload(domain, (MonoObject **)&exc); if (exc) { ERR_PRINT("Exception thrown when unloading scripts domain"); GDMonoUtils::debug_unhandled_exception(exc); return FAILED; } return OK; }
CScriptDomain::~CScriptDomain() { m_bDestroying = true; for each(auto assembly in m_assemblies) delete assembly; m_assemblies.clear(); if(m_bRootDomain) mono_jit_cleanup(m_pDomain); else { if(IsActive()) mono_domain_set(mono_get_root_domain(), false); mono_domain_finalize(m_pDomain, 2000); MonoObject *pException; try { mono_domain_try_unload(m_pDomain, &pException); } catch(char *ex) { MonoWarning("An exception was raised during ScriptDomain unload: %s", ex); } if(pException) { MonoWarning("An exception was raised during ScriptDomain unload:"); MonoMethod *pExceptionMethod = mono_method_desc_search_in_class(mono_method_desc_new("::ToString()", false),mono_get_exception_class()); MonoString *exceptionString = (MonoString *)mono_runtime_invoke(pExceptionMethod, pException, nullptr, nullptr); CryLogAlways(ToCryString((mono::string)exceptionString)); } } g_pScriptSystem->OnDomainReleased(this); }
void MonoManager::unloadScriptDomain() { if (mScriptDomain != nullptr) { onDomainUnload(); mono_domain_set(mono_get_root_domain(), false); mono_domain_finalize(mScriptDomain, 2000); MonoObject* exception = nullptr; mono_domain_try_unload(mScriptDomain, &exception); if (exception != nullptr) MonoUtil::throwIfException(exception); mono_gc_collect(mono_gc_max_generation()); mScriptDomain = nullptr; } for (auto& assemblyEntry : mAssemblies) { assemblyEntry.second->unload(); // Metas hold references to various assembly objects that were just deleted, so clear them Vector<ScriptMeta*>& typeMetas = getScriptMetaData()[assemblyEntry.first]; for (auto& entry : typeMetas) { entry->scriptClass = nullptr; entry->thisPtrField = nullptr; } } mAssemblies.clear(); mIsCoreLoaded = false; }