/* * Try to initialize runtime shutdown. * After this call completes the thread pool will stop accepting new jobs and no further threads will be created. * * @return true if shutdown was initiated by this call or false is other thread beat this one */ gboolean mono_runtime_try_shutdown (void) { if (InterlockedCompareExchange (&shutting_down_inited, TRUE, FALSE)) return FALSE; mono_runtime_fire_process_exit_event (); shutting_down = TRUE; mono_threads_set_shutting_down (); /* No new threads will be created after this point */ mono_runtime_set_shutting_down (); /* This will kill the tp threads which cannot be suspended */ mono_thread_pool_cleanup (); /*TODO move the follow to here: mono_thread_suspend_all_other_threads (); OR mono_thread_wait_all_other_threads mono_runtime_quit (); */ return TRUE; }
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; }
gboolean mono_domain_finalize (MonoDomain *domain, guint32 timeout) { DomainFinalizationReq *req; guint32 res; HANDLE done_event; MonoInternalThread *thread = mono_thread_internal_current (); if (mono_thread_internal_current () == gc_thread) /* We are called from inside a finalizer, not much we can do here */ return FALSE; /* * No need to create another thread 'cause the finalizer thread * is still working and will take care of running the finalizers */ #ifndef HAVE_NULL_GC if (gc_disabled) return TRUE; mono_gc_collect (mono_gc_max_generation ()); done_event = CreateEvent (NULL, TRUE, FALSE, NULL); if (done_event == NULL) { return FALSE; } req = g_new0 (DomainFinalizationReq, 1); req->domain = domain; req->done_event = done_event; if (domain == mono_get_root_domain ()) finalizing_root_domain = TRUE; mono_finalizer_lock (); domains_to_finalize = g_slist_append (domains_to_finalize, req); mono_finalizer_unlock (); /* Tell the finalizer thread to finalize this appdomain */ mono_gc_finalize_notify (); if (timeout == -1) timeout = INFINITE; while (TRUE) { res = WaitForSingleObjectEx (done_event, timeout, TRUE); /* printf ("WAIT RES: %d.\n", res); */ if (res == WAIT_IO_COMPLETION) { if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) return FALSE; } else if (res == WAIT_TIMEOUT) { /* We leak the handle here */ return FALSE; } else { break; } } CloseHandle (done_event); if (domain == mono_get_root_domain ()) { mono_thread_pool_cleanup (); mono_gc_finalize_threadpool_threads (); } return TRUE; #else /* We don't support domain finalization without a GC */ return FALSE; #endif }