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; }
int app_mono_run(struct sip_msg *msg, char *arg) { int ret; char *argv[2]; int argc; sr_mono_load_t *mi; if(_sr_mono_load_list == NULL) return -1; mi = _sr_mono_load_list; LM_DBG("running Mono assembly: [[%s]]\n", mi->script); _sr_M_env.msg = msg; _sr_M_env.domain = mi->domain; _sr_M_env.assembly = mi->assembly; if (_sr_M_env.assembly==NULL) { LM_DBG("empty assembly\n"); memset(&_sr_M_env, 0, sizeof(sr_mono_env_t)); return -1; } mono_domain_set(_sr_M_env.domain, 0); argc = 1; argv[0] = mi->script; if(arg!=NULL) { argc++; argv[1] = arg; } mono_jit_exec(_sr_M_env.domain, _sr_M_env.assembly, argc, argv); ret = mono_environment_exitcode_get(); LM_DBG("returned code from mono environment: %d\n", ret); memset(&_sr_M_env, 0, sizeof(sr_mono_env_t)); return (ret==0)?1:-1; }
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; }
void CPipeServer::SetCurrentDomain(void) { void *domain=(void *)ReadQword(); int r=mono_domain_set(domain, FALSE); WriteDword(r); }
void unload_domain() { MonoDomain* old_domain = mono_domain_get(); if (old_domain && old_domain != mono_get_root_domain()) { if (!mono_domain_set(mono_get_root_domain(), false)) printf_console("Error setting domain\n"); mono_thread_pop_appdomain_ref(); mono_domain_unload(old_domain); } //unloading a domain is also a nice point in time to have the GC run. mono_gc_collect(mono_gc_max_generation()); }
void mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item) { static MonoClass *threadpool_class = NULL; static MonoMethod *unsafe_queue_custom_work_item_method = NULL; MonoDomain *current_domain; MonoBoolean f; gpointer args [2]; g_assert (work_item); if (!threadpool_class) threadpool_class = mono_class_from_name (mono_defaults.corlib, "System.Threading", "ThreadPool"); g_assert (threadpool_class); if (!unsafe_queue_custom_work_item_method) unsafe_queue_custom_work_item_method = mono_class_get_method_from_name (threadpool_class, "UnsafeQueueCustomWorkItem", 2); g_assert (unsafe_queue_custom_work_item_method); f = FALSE; args [0] = (gpointer) work_item; args [1] = (gpointer) mono_value_box (domain, mono_defaults.boolean_class, &f); current_domain = mono_domain_get (); if (current_domain == domain) { mono_runtime_invoke (unsafe_queue_custom_work_item_method, NULL, args, NULL); } else { mono_thread_push_appdomain_ref (domain); if (mono_domain_set (domain, FALSE)) { mono_runtime_invoke (unsafe_queue_custom_work_item_method, NULL, args, NULL); mono_domain_set (current_domain, TRUE); } mono_thread_pop_appdomain_ref (); } }
Error GDMono::_load_scripts_domain() { ERR_FAIL_COND_V(scripts_domain != NULL, ERR_BUG); print_verbose("Mono: Loading scripts domain..."); scripts_domain = GDMonoUtils::create_domain("GodotEngine.ScriptsDomain"); ERR_EXPLAIN("Mono: Could not create scripts app domain"); ERR_FAIL_NULL_V(scripts_domain, ERR_CANT_CREATE); mono_domain_set(scripts_domain, true); return OK; }
MonoDomain* load_domain() { MonoDomain* newDomain = mono_domain_create_appdomain("CCubed Child Domain", NULL); if (!newDomain) { printf("Error creating domain\n"); return nullptr; } mono_thread_push_appdomain_ref(newDomain); if (!mono_domain_set(newDomain, false)) { printf_console("Error setting domain\n"); return nullptr; } return mono_domain_get(); }
Error GDMono::_load_scripts_domain() { ERR_FAIL_COND_V(scripts_domain != NULL, ERR_BUG); if (OS::get_singleton()->is_stdout_verbose()) { OS::get_singleton()->print("Mono: Loading scripts domain...\n"); } scripts_domain = GDMonoUtils::create_domain("GodotEngine.ScriptsDomain"); ERR_EXPLAIN("Mono: Could not create scripts app domain"); ERR_FAIL_NULL_V(scripts_domain, ERR_CANT_CREATE); mono_domain_set(scripts_domain, true); return OK; }
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::loadScriptDomain() { if (mScriptDomain != nullptr) unloadScriptDomain(); if (mScriptDomain == nullptr) { char domainName[] = "ScriptDomain"; mScriptDomain = mono_domain_create_appdomain(domainName, nullptr); mono_domain_set(mScriptDomain, false); if (mScriptDomain == nullptr) { BS_EXCEPT(InternalErrorException, "Cannot create script app domain."); } } if (mScriptDomain != nullptr) { for (auto& assemblyEntry : mAssemblies) initializeAssembly(*assemblyEntry.second); } }
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; }
static void domain_restore(MonoDomain *prev_domain) { if (prev_domain != NULL) mono_domain_set(prev_domain, FALSE); }
bool CScriptDomain::SetActive(bool force) { return mono_domain_set(m_pDomain, force) == 1; }
static void async_invoke_thread (gpointer data) { MonoDomain *domain; MonoInternalThread *thread; MonoWSQ *wsq; ThreadPool *tp; gboolean must_die; const gchar *name; tp = data; wsq = NULL; if (!tp->is_io) wsq = add_wsq (); thread = mono_thread_internal_current (); mono_profiler_thread_start (thread->tid); name = (tp->is_io) ? "IO Threadpool worker" : "Threadpool worker"; mono_thread_set_name_internal (thread, mono_string_new (mono_domain_get (), name), FALSE); if (tp_start_func) tp_start_func (tp_hooks_user_data); data = NULL; for (;;) { MonoAsyncResult *ar; MonoClass *klass; gboolean is_io_task; gboolean is_socket; int n_naps = 0; is_io_task = FALSE; ar = (MonoAsyncResult *) data; if (ar) { InterlockedIncrement (&tp->busy_threads); domain = ((MonoObject *)ar)->vtable->domain; #ifndef DISABLE_SOCKETS klass = ((MonoObject *) data)->vtable->klass; is_io_task = !is_corlib_asyncresult (domain, klass); is_socket = FALSE; if (is_io_task) { MonoSocketAsyncResult *state = (MonoSocketAsyncResult *) data; is_socket = is_socketasyncresult (domain, klass); ar = state->ares; switch (state->operation) { case AIO_OP_RECEIVE: state->total = ICALL_RECV (state); break; case AIO_OP_SEND: state->total = ICALL_SEND (state); break; } } #endif /* worker threads invokes methods in different domains, * so we need to set the right domain here */ g_assert (domain); if (mono_domain_is_unloading (domain) || mono_runtime_is_shutting_down ()) { threadpool_jobs_dec ((MonoObject *)ar); data = NULL; ar = NULL; InterlockedDecrement (&tp->busy_threads); } else { mono_thread_push_appdomain_ref (domain); if (threadpool_jobs_dec ((MonoObject *)ar)) { data = NULL; ar = NULL; mono_thread_pop_appdomain_ref (); InterlockedDecrement (&tp->busy_threads); continue; } if (mono_domain_set (domain, FALSE)) { MonoObject *exc; if (tp_item_begin_func) tp_item_begin_func (tp_item_user_data); if (!is_io_task && ar->add_time > 0) process_idle_times (tp, ar->add_time); exc = mono_async_invoke (tp, ar); if (tp_item_end_func) tp_item_end_func (tp_item_user_data); if (exc) mono_internal_thread_unhandled_exception (exc); if (is_socket && tp->is_io) { MonoSocketAsyncResult *state = (MonoSocketAsyncResult *) data; if (state->completed && state->callback) { MonoAsyncResult *cb_ares; cb_ares = create_simple_asyncresult ((MonoObject *) state->callback, (MonoObject *) state); icall_append_job ((MonoObject *) cb_ares); } } mono_domain_set (mono_get_root_domain (), TRUE); } mono_thread_pop_appdomain_ref (); InterlockedDecrement (&tp->busy_threads); /* If the callee changes the background status, set it back to TRUE */ mono_thread_clr_state (thread , ~ThreadState_Background); if (!mono_thread_test_state (thread , ThreadState_Background)) ves_icall_System_Threading_Thread_SetState (thread, ThreadState_Background); } } ar = NULL; data = NULL; must_die = should_i_die (tp); if (!must_die && (tp->is_io || !mono_wsq_local_pop (&data))) dequeue_or_steal (tp, &data, wsq); n_naps = 0; while (!must_die && !data && n_naps < 4) { gboolean res; InterlockedIncrement (&tp->waiting); // Another thread may have added a job into its wsq since the last call to dequeue_or_steal // Check all the queues again before entering the wait loop dequeue_or_steal (tp, &data, wsq); if (data) { InterlockedDecrement (&tp->waiting); break; } mono_gc_set_skip_thread (TRUE); #if defined(__OpenBSD__) while (mono_cq_count (tp->queue) == 0 && (res = mono_sem_wait (&tp->new_job, TRUE)) == -1) {// && errno == EINTR) { #else while (mono_cq_count (tp->queue) == 0 && (res = mono_sem_timedwait (&tp->new_job, 2000, TRUE)) == -1) {// && errno == EINTR) { #endif if (mono_runtime_is_shutting_down ()) break; if (THREAD_WANTS_A_BREAK (thread)) mono_thread_interruption_checkpoint (); } InterlockedDecrement (&tp->waiting); mono_gc_set_skip_thread (FALSE); if (mono_runtime_is_shutting_down ()) break; must_die = should_i_die (tp); dequeue_or_steal (tp, &data, wsq); n_naps++; } if (!data && !tp->is_io && !mono_runtime_is_shutting_down ()) { mono_wsq_local_pop (&data); if (data && must_die) { InterlockedCompareExchange (&tp->destroy_thread, 1, 0); pulse_on_new_job (tp); } } if (!data) { gint nt; gboolean down; while (1) { nt = tp->nthreads; down = mono_runtime_is_shutting_down (); if (!down && nt <= tp->min_threads) break; if (down || InterlockedCompareExchange (&tp->nthreads, nt - 1, nt) == nt) { mono_perfcounter_update_value (tp->pc_nthreads, TRUE, -1); if (!tp->is_io) { remove_wsq (wsq); } mono_profiler_thread_end (thread->tid); if (tp_finish_func) tp_finish_func (tp_hooks_user_data); return; } } } } g_assert_not_reached (); } void ves_icall_System_Threading_ThreadPool_GetAvailableThreads (gint *workerThreads, gint *completionPortThreads) { *workerThreads = async_tp.max_threads - async_tp.busy_threads; *completionPortThreads = async_io_tp.max_threads - async_io_tp.busy_threads; }