Example #1
0
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;
}
Example #2
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;
}
Example #3
0
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;
}
Example #4
0
void CPipeServer::SetCurrentDomain(void)
{
	void *domain=(void *)ReadQword();
	int r=mono_domain_set(domain, FALSE);

	WriteDword(r);
}
Example #5
0
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());
}
Example #6
0
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 ();
	}
}
Example #7
0
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;
}
Example #8
0
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();
}
Example #9
0
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;
}
Example #10
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;
}
Example #11
0
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;
}
Example #12
0
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;
	}
Example #15
0
static void domain_restore(MonoDomain *prev_domain)
{
    if (prev_domain != NULL)
        mono_domain_set(prev_domain, FALSE);
}
Example #16
0
bool CScriptDomain::SetActive(bool force)
{
	return mono_domain_set(m_pDomain, force) == 1;
}
Example #17
0
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;
}