Ejemplo n.º 1
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 ();
	}
}
Ejemplo n.º 2
0
static MonoException*
continuation_mark_frame (MonoContinuation *cont)
{
	MonoJitTlsData *jit_tls;
	MonoLMF *lmf;
	MonoContext ctx, new_ctx;
	MonoJitInfo *ji, rji;
	int endloop = FALSE;

	if (cont->domain)
		return mono_get_exception_argument ("cont", "Already marked");

	jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
	lmf = mono_get_lmf();
	cont->domain = mono_domain_get ();
	cont->thread_id = GetCurrentThreadId ();

	/* get to the frame that called Mark () */
	memset (&rji, 0, sizeof (rji));
	do {
		ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
		if (!ji || ji == (gpointer)-1) {
			return mono_get_exception_not_supported ("Invalid stack frame");
		}
		ctx = new_ctx;
		if (endloop)
			break;
		if (strcmp (jinfo_get_method (ji)->name, "Mark") == 0)
			endloop = TRUE;
	} while (1);

	cont->top_sp = MONO_CONTEXT_GET_SP (&ctx);
	/*g_print ("method: %s, sp: %p\n", jinfo_get_method (ji)->name, cont->top_sp);*/

	return NULL;
}
Ejemplo n.º 3
0
/**
 * mono_exception_from_name_domain:
 * @domain: Domain where the return object will be created.
 * @image: the Mono image where to look for the class
 * @name_space: the namespace for the class
 * @name: class name
 *
 * Creates an exception object of the given namespace/name class on
 * the given domain.
 *
 * Returns: the initialized exception instance.
 */
MonoException *
mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, 
				 const char* name_space, const char *name)
{
	MonoError error;
	MonoClass *klass;
	MonoObject *o;
	MonoDomain *caller_domain = mono_domain_get ();

	klass = mono_class_load_from_name (image, name_space, name);

	o = mono_object_new_checked (domain, klass, &error);
	mono_error_assert_ok (&error);

	if (domain != caller_domain)
		mono_domain_set_internal (domain);
	mono_runtime_object_init_checked (o, &error);
	mono_error_assert_ok (&error);

	if (domain != caller_domain)
		mono_domain_set_internal (caller_domain);

	return (MonoException *)o;
}
Ejemplo n.º 4
0
/**
 * common_call_trampoline:
 *
 *   The code to handle normal, virtual, and interface method calls and jumps, both
 * from JITted and LLVM compiled code.
 */
static gpointer
common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tramp, MonoVTable *vt, gpointer *vtable_slot, gboolean need_rgctx_tramp)
{
	gpointer addr, compiled_method;
	gboolean generic_shared = FALSE;
	MonoMethod *declaring = NULL;
	MonoMethod *generic_virtual = NULL, *variant_iface = NULL, *orig_method = NULL;
	int context_used;
	gboolean virtual, variance_used = FALSE;
	gpointer *orig_vtable_slot, *vtable_slot_to_patch = NULL;
	MonoJitInfo *ji = NULL;

	virtual = (gpointer)vtable_slot > (gpointer)vt;

	orig_vtable_slot = vtable_slot;
	vtable_slot_to_patch = vtable_slot;

#ifdef MONO_ARCH_HAVE_IMT
	/* IMT call */
	if (vt && (gpointer)vtable_slot < (gpointer)vt) {
		MonoMethod *impl_method = NULL;
		MonoObject *this_arg;

		/* we get the interface method because mono_convert_imt_slot_to_vtable_slot ()
		 * needs the signature to be able to find the this argument
		 */
		m = mono_arch_find_imt_method (regs, code);
		vtable_slot = orig_vtable_slot;
		g_assert (vtable_slot);

		orig_method = m;

		this_arg = mono_arch_get_this_arg_from_call (regs, code);

		if (mono_object_is_transparent_proxy (this_arg)) {
			/* Use the slow path for now */
		    m = mono_object_get_virtual_method (this_arg, m);
			vtable_slot_to_patch = NULL;
		} else {
			addr = NULL;
			vtable_slot = mono_convert_imt_slot_to_vtable_slot (vtable_slot, regs, code, m, &impl_method, &need_rgctx_tramp, &variance_used, &addr);
			/* This is the vcall slot which gets called through the IMT thunk */
			vtable_slot_to_patch = vtable_slot;
			/* mono_convert_imt_slot_to_vtable_slot () also gives us the method that is supposed
			 * to be called, so we compile it and go ahead as usual.
			 */
			/*g_print ("imt found method %p (%s) at %p\n", impl_method, impl_method->name, code);*/
			if (m->is_inflated && ((MonoMethodInflated*)m)->context.method_inst) {
				/* Generic virtual method */
				generic_virtual = m;
				need_rgctx_tramp = TRUE;
			} else if (variance_used && mono_class_has_variant_generic_params (m->klass)) {
				variant_iface = m;
			}

			if (addr && !generic_virtual && !variant_iface) {
				/*
				 * We found AOT compiled code for the method, skip the rest.
				 */
				if (mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot))
					*vtable_slot = addr;

				return mono_create_ftnptr (mono_domain_get (), addr);
			}

			m = impl_method;
		}
	}
#endif

	/*
	 * The virtual check is needed because is_generic_method_definition (m) could
	 * return TRUE for methods used in IMT calls too.
	 */
	if (virtual && is_generic_method_definition (m)) {
		MonoGenericContext context = { NULL, NULL };
		MonoMethod *declaring;

		if (m->is_inflated)
			declaring = mono_method_get_declaring_generic_method (m);
		else
			declaring = m;

		if (m->klass->generic_class)
			context.class_inst = m->klass->generic_class->context.class_inst;
		else
			g_assert (!m->klass->generic_container);

#ifdef MONO_ARCH_HAVE_IMT
		generic_virtual = mono_arch_find_imt_method (regs, code);
#endif
		if (generic_virtual) {
			g_assert (generic_virtual->is_inflated);
			context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
		}

		m = mono_class_inflate_generic_method (declaring, &context);
		/* FIXME: only do this if the method is sharable */
		need_rgctx_tramp = TRUE;
	} else if ((context_used = mono_method_check_context_used (m))) {
Ejemplo n.º 5
0
mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *code, MonoMethod *method, MonoMethod **impl_method, gboolean *need_rgctx_tramp, gboolean *variance_used, gpointer *aot_addr)
{
	MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code);
	MonoVTable *vt = this_argument->vtable;
	int displacement = slot - ((gpointer*)vt);

	if (displacement > 0) {
		/* slot is in the vtable, not in the IMT */
#if DEBUG_IMT
		printf ("mono_convert_imt_slot_to_vtable_slot: slot %p is in the vtable, not in the IMT\n", slot);
#endif
		return slot;
	} else {
		MonoMethod *imt_method = mono_arch_find_imt_method (regs, code);
		MonoMethod *impl;
		int interface_offset;
		int imt_slot = MONO_IMT_SIZE + displacement;

		/*This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement*/
		interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, variance_used);

		if (interface_offset < 0) {
			g_error ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, 0), mono_type_get_name_full (&imt_method->klass->byval_arg, 0));
		}
		mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));

		if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
			MonoGenericContext context = { NULL, NULL };

			/* 
			 * Generic virtual method, imt_method contains the inflated interface 
			 * method, need to get the inflated impl method.
			 */
			/* imt_method->slot might not be set */
			impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot);

			if (impl->klass->generic_class)
				context.class_inst = impl->klass->generic_class->context.class_inst;
			context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
			impl = mono_class_inflate_generic_method (impl, &context);
		} else {
			/* Avoid loading metadata or creating a generic vtable if possible */
			if (!vt->klass->valuetype)
				*aot_addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method));
			else
				*aot_addr = NULL;
			if (*aot_addr)
				impl = NULL;
			else
				impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_vtable_slot (imt_method));
		}

		if (impl && mono_method_needs_static_rgctx_invoke (impl, FALSE))
			*need_rgctx_tramp = TRUE;
		if (impl && impl->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
			WrapperInfo *info = mono_marshal_get_wrapper_info (impl);

			if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) {
				// FIXME: This needs a gsharedvt-out trampoline, since the caller uses the gsharedvt calling conv, but the
				// wrapper is a normal non-generic method.
				*need_rgctx_tramp = TRUE;
				//g_assert_not_reached ();
			}
		}

		*impl_method = impl;
#if DEBUG_IMT
		printf ("mono_convert_imt_slot_to_vtable_slot: method = %s.%s.%s, imt_method = %s.%s.%s\n",
				method->klass->name_space, method->klass->name, method->name, 
				imt_method->klass->name_space, imt_method->klass->name, imt_method->name);
#endif

		g_assert (imt_slot < MONO_IMT_SIZE);
		if (vt->imt_collisions_bitmap & (1 << imt_slot)) {
			int slot = mono_method_get_vtable_index (imt_method);
			int vtable_offset;
			gpointer *vtable_slot;

			g_assert (slot != -1);
			vtable_offset = interface_offset + slot;
			vtable_slot = & (vt->vtable [vtable_offset]);
#if DEBUG_IMT
			printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, and colliding becomes %p[%d] (interface_offset = %d, method->slot = %d)\n", slot, imt_slot, vtable_slot, vtable_offset, interface_offset, imt_method->slot);
#endif
			return vtable_slot;
		} else {
#if DEBUG_IMT
			printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, but not colliding\n", slot, imt_slot);
#endif
			return slot;
		}
	}
}
Ejemplo n.º 6
0
/*Can fail with out-of-memory*/
MonoException*
mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
{
	MonoErrorInternal *error = (MonoErrorInternal*)oerror;

	MonoException* exception = NULL;
	MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
	MonoDomain *domain = mono_domain_get ();

	mono_error_init (error_out);

	switch (error->error_code) {
	case MONO_ERROR_NONE:
		return NULL;

	case MONO_ERROR_MISSING_METHOD:
		if ((error->type_name || error->exn.klass) && error->member_name) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;

			method_name = mono_string_new (domain, error->member_name);
			if (!method_name) {
				mono_error_set_out_of_memory (error_out, "Could not allocate method name");
				break;
			}

			exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name, error_out);
			if (exception)
				set_message_on_exception (exception, error, error_out);
		} else {
			exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", error->full_message);
		}
		break;

	case MONO_ERROR_MISSING_FIELD:
		if ((error->type_name || error->exn.klass) && error->member_name) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;
			
			field_name = mono_string_new (domain, error->member_name);
			if (!field_name) {
				mono_error_set_out_of_memory (error_out, "Could not allocate field name");
				break;
			}
			
			exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name, error_out);
			if (exception)
				set_message_on_exception (exception, error, error_out);
		} else {
			exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", error->full_message);
		}
		break;

	case MONO_ERROR_TYPE_LOAD:
		if ((error->type_name && error->assembly_name) || error->exn.klass) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;

			if (error->assembly_name) {
				assembly_name = mono_string_new (domain, error->assembly_name);
				if (!assembly_name) {
					mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
					break;
				}
			}

			exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name, error_out);
			if (exception)
				set_message_on_exception (exception, error, error_out);
		} else {
			exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message);
		}
		break;

	case MONO_ERROR_FILE_NOT_FOUND:
	case MONO_ERROR_BAD_IMAGE:
		if (error->assembly_name) {
			msg = mono_string_new (domain, error->full_message);
			if (!msg) {
				mono_error_set_out_of_memory (error_out, "Could not allocate message");
				break;
			}

			if (error->assembly_name) {
				assembly_name = mono_string_new (domain, error->assembly_name);
				if (!assembly_name) {
					mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
					break;
				}
			}

			if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
				exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name, error_out);
			else
				exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name, error_out);
		} else {
			if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
				exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message);
			else
				exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", error->full_message);
		}
		break;

	case MONO_ERROR_OUT_OF_MEMORY:
		exception = mono_get_exception_out_of_memory ();
		break;

	case MONO_ERROR_ARGUMENT:
		exception = mono_get_exception_argument (error->first_argument, error->full_message);
		break;

	case MONO_ERROR_ARGUMENT_NULL:
		exception = mono_get_exception_argument_null (error->first_argument);
		break;

	case MONO_ERROR_NOT_VERIFIABLE: {
		char *type_name = NULL, *message;
		if (error->exn.klass) {
			type_name = mono_type_get_full_name (error->exn.klass);
			if (!type_name) {
				mono_error_set_out_of_memory (error_out, "Could not allocate message");
				break;
			}
		}
		message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, error->full_message);
		if (!message) {
			g_free (type_name);
			mono_error_set_out_of_memory (error_out, "Could not allocate message");
			break;	
		}
		exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
		g_free (message);
		g_free (type_name);
		break;
	}
	case MONO_ERROR_GENERIC:
		if (!error->exception_name_space || !error->exception_name)
			mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied");
		else
			exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message);
		break;

	case MONO_ERROR_EXCEPTION_INSTANCE:
		exception = (MonoException*) mono_gchandle_get_target (error->exn.instance_handle);
		break;

	case MONO_ERROR_CLEANUP_CALLED_SENTINEL:
		mono_error_set_execution_engine (error_out, "MonoError reused after mono_error_cleanup");
		break;

	case MONO_ERROR_INVALID_PROGRAM: {
		gboolean lacks_message = error->flags & MONO_ERROR_INCOMPLETE;
		if (lacks_message)
			return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
		else
			return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", error->full_message);
	}
	default:
		mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
	}

	if (!mono_error_ok (error_out))
		return NULL;
	if (!exception)
		mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
	return exception;
}
Ejemplo n.º 7
0
/* 
 * actually, we might want to queue the finalize requests in a separate thread,
 * but we need to be careful about the execution domain of the thread...
 */
void
mono_gc_run_finalize (void *obj, void *data)
{
	MonoObject *exc = NULL;
	MonoObject *o;
#ifndef HAVE_SGEN_GC
	MonoObject *o2;
#endif
	MonoMethod* finalizer = NULL;
	MonoDomain *caller_domain = mono_domain_get ();
	MonoDomain *domain;
	RuntimeInvokeFunction runtime_invoke;
	GSList *l, *refs = NULL;

	o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));

	if (suspend_finalizers)
		return;

	domain = o->vtable->domain;

#ifndef HAVE_SGEN_GC
	mono_domain_finalizers_lock (domain);

	o2 = g_hash_table_lookup (domain->finalizable_objects_hash, o);

	refs = mono_gc_remove_weak_track_object (domain, o);

	mono_domain_finalizers_unlock (domain);

	if (!o2)
		/* Already finalized somehow */
		return;
#endif

	if (refs) {
		/*
		 * Support for GCHandles of type WeakTrackResurrection:
		 *
		 *   Its not exactly clear how these are supposed to work, or how their
		 * semantics can be implemented. We only implement one crucial thing:
		 * these handles are only cleared after the finalizer has ran.
		 */
		for (l = refs; l; l = l->next) {
			guint32 gchandle = GPOINTER_TO_UINT (l->data);

			mono_gchandle_set_target (gchandle, o);
		}

		g_slist_free (refs);
	}
		
	/* make sure the finalizer is not called again if the object is resurrected */
	object_register_finalizer (obj, NULL);

	if (o->vtable->klass == mono_defaults.internal_thread_class) {
		MonoInternalThread *t = (MonoInternalThread*)o;

		if (mono_gc_is_finalizer_internal_thread (t))
			/* Avoid finalizing ourselves */
			return;

		if (t->threadpool_thread && finalizing_root_domain) {
			/* Don't finalize threadpool threads when
			   shutting down - they're finalized when the
			   threadpool shuts down. */
			add_thread_to_finalize (t);
			return;
		}
	}

	if (o->vtable->klass->image == mono_defaults.corlib && !strcmp (o->vtable->klass->name, "DynamicMethod") && finalizing_root_domain) {
		/*
		 * These can't be finalized during unloading/shutdown, since that would
		 * free the native code which can still be referenced by other
		 * finalizers.
		 * FIXME: This is not perfect, objects dying at the same time as 
		 * dynamic methods can still reference them even when !shutdown.
		 */
		return;
	}

	if (mono_runtime_get_no_exec ())
		return;

	/* speedup later... and use a timeout */
	/* g_print ("Finalize run on %p %s.%s\n", o, mono_object_class (o)->name_space, mono_object_class (o)->name); */

	/* Use _internal here, since this thread can enter a doomed appdomain */
	mono_domain_set_internal (mono_object_domain (o));

	/* delegates that have a native function pointer allocated are
	 * registered for finalization, but they don't have a Finalize
	 * method, because in most cases it's not needed and it's just a waste.
	 */
	if (o->vtable->klass->delegate) {
		MonoDelegate* del = (MonoDelegate*)o;
		if (del->delegate_trampoline)
			mono_delegate_free_ftnptr ((MonoDelegate*)o);
		mono_domain_set_internal (caller_domain);
		return;
	}

	finalizer = mono_class_get_finalizer (o->vtable->klass);

#ifndef DISABLE_COM
	/* If object has a CCW but has no finalizer, it was only
	 * registered for finalization in order to free the CCW.
	 * Else it needs the regular finalizer run.
	 * FIXME: what to do about ressurection and suppression
	 * of finalizer on object with CCW.
	 */
	if (mono_marshal_free_ccw (o) && !finalizer) {
		mono_domain_set_internal (caller_domain);
		return;
	}
#endif

	/* 
	 * To avoid the locking plus the other overhead of mono_runtime_invoke (),
	 * create and precompile a wrapper which calls the finalize method using
	 * a CALLVIRT.
	 */
	if (!domain->finalize_runtime_invoke) {
		MonoMethod *invoke = mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE);

		domain->finalize_runtime_invoke = mono_compile_method (invoke);
	}

	runtime_invoke = domain->finalize_runtime_invoke;

	mono_runtime_class_init (o->vtable);

	runtime_invoke (o, NULL, &exc, NULL);

	if (exc) {
		/* fixme: do something useful */
	}

	mono_domain_set_internal (caller_domain);
}
Ejemplo n.º 8
0
bool Application::StartMonoAndLoadAssemblies()
{
	// shutdown the child domain
	StopMono();

	// create a new child domain
	if (!StartMono()) {
		mono_environment_exitcode_set(-1);
		return true;
	}


	std::string dll = "EmbedThings.dll";
	std::string filename = File::BuildRootedPath(assemblyDir, dll);
	size_t length;
	// read our entry point assembly
	char* data = File::Read(filename.c_str(), &length);

	printf_console("Loading %s into Domain\n", dll.c_str());

	MonoImageOpenStatus status;
	// open the assembly from the data we read, so we never lock files
	auto image = mono_image_open_from_data_with_name(data, length, true /* copy data */, &status, false /* ref only */, filename.c_str());
	if (status != MONO_IMAGE_OK || image == nullptr)
	{
		printf_console("Failed loading assembly %s\n", dll);
		return true;
	}

	// load the assembly
	auto  assembly = mono_assembly_load_from_full(image, filename.c_str(), &status, false);
	if (status != MONO_IMAGE_OK || assembly == nullptr)
	{
		mono_image_close(image);
		printf_console("Failed loading assembly %s\n", dll);
		return true;
	}

	// save the image for lookups later and for cleaning up
	images.push_back(image);

	if (!assembly) {
		printf_console("Couldn't find assembly %s\n", filename.c_str());
		return true;
	}

	// locate the class we want to load
	MonoClass* klass = mono_class_from_name(image, "EmbedThings", "EntryPoint");
	if (klass == nullptr) {
		printf_console("Failed loading class %s\n", "EmbedThings.EntryPoint");
		return true;
	}

	// create the class (doesn't run constructors)
	MonoObject* obj = mono_object_new(mono_domain_get(), klass);
	if (obj == nullptr) {
		printf_console("Failed loading class instance %s\n", "EmbedThings.EntryPoint");
		return true;
	}

	// initialize the class instance (runs default constructors)
	mono_runtime_object_init(obj);
	if (obj == nullptr) {
		printf_console("Failed initializing class instance %s\n", "EmbedThings.EntryPoint");
		return true;
	}

	// save the class instance for lookups later
	instances.push_back(obj);

	// find the Run() method
	auto method = find_method(klass, "Run");
	MonoObject *result, *exception;

	// call the Run method. This will block until the managed code decides to exit
	result = mono_runtime_invoke(method, obj, NULL, NULL);
	int val = *(int*)mono_object_unbox(result);

	// if the managed code returns with 0, it wants to exit completely
	if (val == 0) {
		return true;
	}
	return false;
}
Ejemplo n.º 9
0
void
mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf)
{
#ifdef MONO_CROSS_COMPILE
	g_assert_not_reached ();
#else
#ifdef MONO_ARCH_USE_SIGACTION
	os_ucontext *uc = (ucontext_t*)sigctx;
	os_ucontext *uc_copy;
	MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (sigctx), NULL);
	gpointer *sp;
	int frame_size;

	if (stack_ovf) {
		const char *method;
		/* we don't do much now, but we can warn the user with a useful message */
		fprintf (stderr, "Stack overflow: IP: %p, SP: %p\n", mono_arch_ip_from_context (sigctx), (gpointer)UCONTEXT_REG_Rn(uc, 1));
		if (ji && !ji->is_trampoline && jinfo_get_method (ji))
			method = mono_method_full_name (jinfo_get_method (ji), TRUE);
		else
			method = "Unmanaged";
		fprintf (stderr, "At %s\n", method);
		abort ();
	}
	if (!ji)
		mono_handle_native_crash ("SIGSEGV", sigctx, siginfo);
	/* setup a call frame on the real stack so that control is returned there
	 * and exception handling can continue.
	 * The frame looks like:
	 *   ucontext struct
	 *   ...
	 * 224 is the size of the red zone
	 */
	frame_size = sizeof (ucontext_t) + sizeof (gpointer) * 16 + 224;
	frame_size += 15;
	frame_size &= ~15;
	sp = (gpointer)(UCONTEXT_REG_Rn(uc, 1) & ~15);
	sp = (gpointer)((char*)sp - frame_size);
	/* may need to adjust pointers in the new struct copy, depending on the OS */
	uc_copy = (ucontext_t*)(sp + 16);
	memcpy (uc_copy, uc, sizeof (os_ucontext));
#if defined(__linux__) && !defined(__mono_ppc64__)
	uc_copy->uc_mcontext.uc_regs = (gpointer)((char*)uc_copy + ((char*)uc->uc_mcontext.uc_regs - (char*)uc));
#endif
	g_assert (mono_arch_ip_from_context (uc) == mono_arch_ip_from_context (uc_copy));
	/* at the return form the signal handler execution starts in altstack_handle_and_restore() */
	UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc);
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
	{
		MonoPPCFunctionDescriptor *handler_ftnptr = (MonoPPCFunctionDescriptor*)altstack_handle_and_restore;

		UCONTEXT_REG_NIP(uc) = (gulong)handler_ftnptr->code;
		UCONTEXT_REG_Rn(uc, 2) = (gulong)handler_ftnptr->toc;
	}
#else
	UCONTEXT_REG_NIP(uc) = (unsigned long)altstack_handle_and_restore;
#if _CALL_ELF == 2
	/* ELF v2 ABI calling convention requires to put the target address into
	* r12 if we use the global entry point of a function. */
	UCONTEXT_REG_Rn(uc, 12) = (unsigned long) altstack_handle_and_restore;
#endif
#endif
	UCONTEXT_REG_Rn(uc, 1) = (unsigned long)sp;
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG) = (unsigned long)(sp + 16);
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 1) = 0;
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 2) = 0;
#endif

#endif /* !MONO_CROSS_COMPILE */
}
Ejemplo n.º 10
0
static void
SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
{
	int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
	MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
	GET_CONTEXT;
	
	if (call_chain_depth == 0) {
		mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
	} else {
		MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
		int current_frame_index = 1;
		MonoContext mono_context;
		guchar *ips [call_chain_depth + 1];

		mono_arch_sigctx_to_monoctx (ctx, &mono_context);
		ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
		
		if (jit_tls != NULL) {
			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
#if FULL_STAT_PROFILER_BACKTRACE
			guchar *current_frame;
			guchar *stack_bottom;
			guchar *stack_top;
			
			stack_bottom = jit_tls->end_of_stack;
			stack_top = MONO_CONTEXT_GET_SP (&mono_context);
			current_frame = MONO_CONTEXT_GET_BP (&mono_context);
			
			while ((current_frame_index <= call_chain_depth) &&
					(stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
					((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
				ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
				current_frame_index ++;
				stack_top = current_frame;
				current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
			}
#else
				call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
#endif
			}
			
			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
#if GLIBC_PROFILER_BACKTRACE
				current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
#else
				call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
#endif
			}

			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
				MonoDomain *domain = mono_domain_get ();
				if (domain != NULL) {
					MonoLMF *lmf = NULL;
					MonoJitInfo *ji;
					MonoJitInfo res;
					MonoContext new_mono_context;
					int native_offset;
					ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
							&new_mono_context, NULL, &lmf, &native_offset, NULL);
					while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
						ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
						current_frame_index ++;
						mono_context = new_mono_context;
						ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
								&new_mono_context, NULL, &lmf, &native_offset, NULL);
					}
				}
			}
		}
		
		mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
	}

	mono_chain_signal (SIG_HANDLER_PARAMS);
}
Ejemplo n.º 11
0
static void
SIG_HANDLER_SIGNATURE (sigusr1_signal_handler)
{
	gboolean running_managed;
	MonoException *exc;
	MonoInternalThread *thread = mono_thread_internal_current ();
	MonoDomain *domain = mono_domain_get ();
	void *ji;
	
	GET_CONTEXT;

	if (!thread || !domain)
		/* The thread might not have started up yet */
		/* FIXME: Specify the synchronization with start_wrapper () in threads.c */
		return;

	if (thread->thread_dump_requested) {
		thread->thread_dump_requested = FALSE;

		mono_print_thread_dump (ctx);
	}

	/*
	 * This is an async signal, so the code below must not call anything which
	 * is not async safe. That includes the pthread locking functions. If we
	 * know that we interrupted managed code, then locking is safe.
	 */
	/*
	 * On OpenBSD, ctx can be NULL if we are interrupting poll ().
	 */
	if (ctx) {
		ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
		running_managed = ji != NULL;

		if (mono_debugger_agent_thread_interrupt (ctx, ji))
			return;
	} else {
		running_managed = FALSE;
	}

	/* We can't do handler block checking from metadata since it requires doing
	 * a stack walk with context.
	 *
	 * FIXME add full-aot support.
	 */
#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
	if (!mono_aot_only && ctx) {
		MonoThreadUnwindState unwind_state;
		if (mono_thread_state_init_from_sigctx (&unwind_state, ctx)) {
			if (mono_install_handler_block_guard (&unwind_state)) {
#ifndef HOST_WIN32
				/*Clear current thread from been wapi interrupted otherwise things can go south*/
				wapi_clear_interruption ();
#endif
				return;
			}
		}
	}
#endif

	exc = mono_thread_request_interruption (running_managed); 
	if (!exc)
		return;

	mono_arch_handle_exception (ctx, exc, FALSE);
}
Ejemplo n.º 12
0
MonoArray * 
ves_icall_System_String_InternalSplit (MonoString *me, MonoArray *separator, gint32 count, gint32 options)
{
	static MonoClass *String_array;
	MonoString * tmpstr;
	MonoArray * retarr;
	gunichar2 *src;
	gint32 arrsize, srcsize, splitsize;
	gint32 i, lastpos, arrpos;
	gint32 tmpstrsize;
	gint32 remempty;
	gint32 flag;
	gunichar2 *tmpstrptr;

	remempty = options & STRINGSPLITOPTIONS_REMOVE_EMPTY_ENTRIES;
	src = mono_string_chars (me);
	srcsize = mono_string_length (me);
	arrsize = mono_array_length (separator);

	if (!String_array) {
		MonoClass *klass = mono_array_class_get (mono_get_string_class (), 1);
		mono_memory_barrier ();
		String_array = klass;
	}

	splitsize = 1;
	/* Count the number of elements we will return. Note that this operation
	 * guarantees that we will return exactly splitsize elements, and we will
	 * have enough data to fill each. This allows us to skip some checks later on.
	 */
	if (remempty == 0) {
		for (i = 0; i != srcsize && splitsize < count; i++) {
			if (string_icall_is_in_array (separator, arrsize, src [i]))
				splitsize++;
		}
	} else if (count > 1) {
		/* Require pattern "Nondelim + Delim + Nondelim" to increment counter.
		 * Lastpos != 0 means first nondelim found.
		 * Flag = 0 means last char was delim.
		 * Efficient, though perhaps confusing.
		 */
		lastpos = 0;
		flag = 0;
		for (i = 0; i != srcsize && splitsize < count; i++) {
			if (string_icall_is_in_array (separator, arrsize, src [i])) {
				flag = 0;
			} else if (flag == 0) {
				if (lastpos == 1)
					splitsize++;
				flag = 1;
				lastpos = 1;
			}
		}

		/* Nothing but separators */
		if (lastpos == 0) {
			retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), 0);
			return retarr;
		}
	}

	/* if no split chars found return the string */
	if (splitsize == 1) {
		if (remempty == 0 || count == 1) {
			/* Copy the whole string */
			retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), 1);
			mono_array_setref (retarr, 0, me);
		} else {
			/* otherwise we have to filter out leading & trailing delims */

			/* find first non-delim char */
			for (; srcsize != 0; srcsize--, src++) {
				if (!string_icall_is_in_array (separator, arrsize, src [0]))
					break;
			}
			/* find last non-delim char */
			for (; srcsize != 0; srcsize--) {
				if (!string_icall_is_in_array (separator, arrsize, src [srcsize - 1]))
					break;
			}
			tmpstr = mono_string_new_size (mono_domain_get (), srcsize);
			tmpstrptr = mono_string_chars (tmpstr);

			memcpy (tmpstrptr, src, srcsize * sizeof (gunichar2));
			retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), 1);
			mono_array_setref (retarr, 0, tmpstr);
		}
		return retarr;
	}

	lastpos = 0;
	arrpos = 0;
	
	retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), splitsize);

	for (i = 0; i != srcsize && arrpos != splitsize; i++) {
		if (string_icall_is_in_array (separator, arrsize, src [i])) {
			
			if (lastpos != i || remempty == 0) {
				tmpstrsize = i - lastpos;
				tmpstr = mono_string_new_size (mono_domain_get (), tmpstrsize);
				tmpstrptr = mono_string_chars (tmpstr);

				memcpy (tmpstrptr, src + lastpos, tmpstrsize * sizeof (gunichar2));
				mono_array_setref (retarr, arrpos, tmpstr);
				arrpos++;

				if (arrpos == splitsize - 1) {
					/* Shortcut the last array element */

					lastpos = i + 1;
					if (remempty != 0) {
						/* Search for non-delim starting char (guaranteed to find one) Note that loop
						 * condition is only there for safety. It will never actually terminate the loop. */
						for (; lastpos != srcsize ; lastpos++) {
							if (!string_icall_is_in_array (separator, arrsize, src [lastpos])) 
								break;
						}
						if (count > splitsize) {
							/* Since we have fewer results than our limit, we must remove
							 * trailing delimiters as well. 
							 */
							for (; srcsize != lastpos + 1 ; srcsize--) {
								if (!string_icall_is_in_array (separator, arrsize, src [srcsize - 1])) 
									break;
							}
						}
					}

					tmpstrsize = srcsize - lastpos;
					tmpstr = mono_string_new_size (mono_domain_get (), tmpstrsize);
					tmpstrptr = mono_string_chars (tmpstr);

					memcpy (tmpstrptr, src + lastpos, tmpstrsize * sizeof (gunichar2));
					mono_array_setref (retarr, arrpos, tmpstr);

					/* Loop will ALWAYS end here. Test criteria in the FOR loop is technically unnecessary. */
					break;
				}
			}
			lastpos = i + 1;
		}
	}

	return retarr;
}
Ejemplo n.º 13
0
static void
monitor_thread (gpointer unused)
{
	ThreadPool *pools [2];
	MonoInternalThread *thread;
	int i;

	guint32 ms;
	gint8 num_waiting_iterations = 0;

	gint16 history_size = 0, current = -1;
	SamplesHistory *history = malloc (sizeof (SamplesHistory) * HISTORY_SIZE);

	pools [0] = &async_tp;
	pools [1] = &async_io_tp;
	thread = mono_thread_internal_current ();
	ves_icall_System_Threading_Thread_SetName_internal (thread, mono_string_new (mono_domain_get (), "Threadpool monitor"));
	while (1) {
		ms = SAMPLES_PERIOD;
		i = 10; //number of spurious awakes we tolerate before doing a round of rebalancing.
		do {
			guint32 ts;
			ts = mono_msec_ticks ();
			if (SleepEx (ms, TRUE) == 0)
				break;
			ms -= (mono_msec_ticks () - ts);
			if (mono_runtime_is_shutting_down ())
				break;
			if (THREAD_WANTS_A_BREAK (thread))
				mono_thread_interruption_checkpoint ();
		} while (ms > 0 && i--);

		if (mono_runtime_is_shutting_down ())
			break;

		if (suspended)
			continue;

		/* threadpool is cleaning up */
		if (async_tp.pool_status == 2 || async_io_tp.pool_status == 2)
			break;

		switch (monitor_state) {
		case MONITOR_STATE_AWAKE:
			num_waiting_iterations = 0;
			break;
		case MONITOR_STATE_FALLING_ASLEEP:
			if (++num_waiting_iterations == NUM_WAITING_ITERATIONS) {
				if (monitor_state == MONITOR_STATE_FALLING_ASLEEP && InterlockedCompareExchange (&monitor_state, MONITOR_STATE_SLEEPING, MONITOR_STATE_FALLING_ASLEEP) == MONITOR_STATE_FALLING_ASLEEP) {
					MONO_SEM_WAIT (&monitor_sem);

					num_waiting_iterations = 0;
					current = -1;
					history_size = 0;
				}
			}
			break;
		case MONITOR_STATE_SLEEPING:
			g_assert_not_reached ();
		}

		for (i = 0; i < 2; i++) {
			ThreadPool *tp;
			tp = pools [i];

			if (tp->is_io) {
				if (!tp->waiting && mono_cq_count (tp->queue) > 0)
					threadpool_start_thread (tp);
			} else {
				gint8 nthreads_diff = monitor_heuristic (&current, &history_size, history, tp);

				if (nthreads_diff == 1)
					threadpool_start_thread (tp);
				else if (nthreads_diff == -1)
					threadpool_kill_thread (tp);
			}
		}
	}
}
Ejemplo n.º 14
0
/*Can fail with out-of-memory*/
MonoException*
mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
{
	MonoErrorInternal *error = (MonoErrorInternal*)oerror;

	MonoException* exception = NULL;
	MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
	MonoDomain *domain = mono_domain_get ();

	mono_error_init (error_out);

	switch (error->error_code) {
	case MONO_ERROR_NONE:
		return NULL;

	case MONO_ERROR_MISSING_METHOD:
		if ((error->type_name || error->klass) && error->member_name) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;

			method_name = mono_string_new (domain, error->member_name);
			if (!method_name) {
				mono_error_set_out_of_memory (error_out, "Could not allocate method name");
				break;
			}

			exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
			if (exception)
				set_message_on_exception (exception, error, error_out);
		} else {
		 	exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", mono_internal_error_get_message (error));
		}
		break;

	case MONO_ERROR_MISSING_FIELD:
		if ((error->type_name || error->klass) && error->member_name) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;
			
			field_name = mono_string_new (domain, error->member_name);
			if (!field_name) {
				mono_error_set_out_of_memory (error_out, "Could not allocate field name");
				break;
			}
			
			exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
			if (exception)
				set_message_on_exception (exception, error, error_out);
		} else {
		 	exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", mono_internal_error_get_message (error));
		}
		break;

	case MONO_ERROR_TYPE_LOAD:
		if (error->type_name || error->assembly_name) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;

			if (error->assembly_name) {
				assembly_name = mono_string_new (domain, error->assembly_name);
				if (!assembly_name) {
					mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
					break;
				}
			}

			exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
			if (exception)
				set_message_on_exception (exception, error, error_out);
		} else {
		 	exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", mono_internal_error_get_message (error));
		}
		break;

	case MONO_ERROR_FILE_NOT_FOUND:
	case MONO_ERROR_BAD_IMAGE:
		if (error->assembly_name) {
			msg = mono_string_new (domain, mono_internal_error_get_message (error));
			if (!msg) {
				mono_error_set_out_of_memory (error_out, "Could not allocate message");
				break;
			}

			if (error->assembly_name) {
				assembly_name = mono_string_new (domain, error->assembly_name);
				if (!assembly_name) {
					mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
					break;
				}
			}

			if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
				exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
			else
				exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
		} else {
			if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
				exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", mono_internal_error_get_message (error));
			else
				exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", mono_internal_error_get_message (error));
		}
		break;

	case MONO_ERROR_OUT_OF_MEMORY:
		exception = mono_get_exception_out_of_memory ();
		break;

	case MONO_ERROR_ARGUMENT:
		exception = mono_get_exception_argument (error->type_name, mono_internal_error_get_message (error));
		break;

	case MONO_ERROR_NOT_VERIFIABLE: {
		char *type_name = NULL, *message;
		if (error->klass) {
			type_name = mono_type_get_full_name (error->klass);
			if (!type_name) {
				mono_error_set_out_of_memory (error_out, "Could not allocate message");
				break;
			}
		}
		message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, mono_internal_error_get_message (error));
		if (!message) {
			g_free (type_name);
			mono_error_set_out_of_memory (error_out, "Could not allocate message");
			break;	
		}
		exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
		g_free (message);
		g_free (type_name);
		break;
	}
	case MONO_ERROR_GENERIC:
		if (!error->exception_name_space || !error->exception_name)
			mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "MonoError with generic error but no exception name was supplied");
		else
			exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, mono_internal_error_get_message (error));
		break;

	default:
		mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "Invalid error-code %d", error->error_code);
	}

	if (!mono_error_ok (error_out))
		return NULL;
	if (!exception)
		mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
	return exception;
}
Ejemplo n.º 15
0
static MonoString *string_invariant_replace (MonoString *me,
					     MonoString *oldValue,
					     MonoString *newValue)
{
	MonoString *ret;
	gunichar2 *src;
	gunichar2 *dest=NULL; /* shut gcc up */
	gunichar2 *oldstr;
	gunichar2 *newstr=NULL; /* shut gcc up here too */
	gint32 i, destpos;
	gint32 occurr;
	gint32 newsize;
	gint32 oldstrlen;
	gint32 newstrlen;
	gint32 srclen;

	occurr = 0;
	destpos = 0;

	oldstr = mono_string_chars(oldValue);
	oldstrlen = mono_string_length(oldValue);

	if (NULL != newValue) {
		newstr = mono_string_chars(newValue);
		newstrlen = mono_string_length(newValue);
	} else
		newstrlen = 0;

	src = mono_string_chars(me);
	srclen = mono_string_length(me);

	if (oldstrlen != newstrlen) {
		i = 0;
		while (i <= srclen - oldstrlen) {
			if (0 == memcmp(src + i, oldstr, oldstrlen * sizeof(gunichar2))) {
				occurr++;
				i += oldstrlen;
			}
			else
				i ++;
		}
		if (occurr == 0)
			return me;
		newsize = srclen + ((newstrlen - oldstrlen) * occurr);
	} else
		newsize = srclen;

	ret = NULL;
	i = 0;
	while (i < srclen) {
		if (0 == memcmp(src + i, oldstr, oldstrlen * sizeof(gunichar2))) {
			if (ret == NULL) {
				ret = mono_string_new_size( mono_domain_get (), newsize);
				dest = mono_string_chars(ret);
				memcpy (dest, src, i * sizeof(gunichar2));
			}
			if (newstrlen > 0) {
				memcpy(dest + destpos, newstr, newstrlen * sizeof(gunichar2));
				destpos += newstrlen;
			}
			i += oldstrlen;
			continue;
		} else if (ret != NULL) {
			dest[destpos] = src[i];
		}
		destpos++;
		i++;
	}
	
	if (ret == NULL)
		return me;

	return ret;
}
Ejemplo n.º 16
0
MonoExceptionHandle
mono_get_exception_reflection_type_load_checked (MonoArrayHandle types, MonoArrayHandle exceptions, MonoError *error)
{
	HANDLE_FUNCTION_ENTER ();

	MonoClass *klass;
	MonoMethod *method;
	gpointer iter;

	error_init (error);

	klass = mono_class_load_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException");

	mono_class_init_internal (klass);

	/* Find the Type[], Exception[] ctor */
	iter = NULL;
	while ((method = mono_class_get_methods (klass, &iter))) {
		if (!strcmp (".ctor", mono_method_get_name (method))) {
			MonoMethodSignature *sig = mono_method_signature_internal (method);

			if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_SZARRAY && sig->params [1]->type == MONO_TYPE_SZARRAY)
				break;
		}
		method = NULL;
	}
	g_assert (method);

	MonoExceptionHandle exc = MONO_HANDLE_CAST (MonoException, MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (mono_domain_get (), klass, error)));
	mono_error_assert_ok (error);

	gpointer args [ ] = { MONO_HANDLE_RAW (types), MONO_HANDLE_RAW (exceptions) };

	mono_runtime_invoke_checked (method, MONO_HANDLE_RAW (exc), args, error);
	goto_if_nok (error, return_null);
	goto exit;
return_null:
	exc = MONO_HANDLE_CAST (MonoException, mono_new_null ());
exit:
	HANDLE_FUNCTION_RETURN_REF (MonoException, exc);
}
Ejemplo n.º 17
0
/**
 * mono_exception_new_by_name:
 * \param image the Mono image where to look for the class
 * \param name_space the namespace for the class
 * \param name class name
 *
 * Creates an exception of the given namespace/name class in the
 * current domain.
 *
 * \returns the initialized exception instance.
 */
static MonoExceptionHandle
mono_exception_new_by_name (MonoImage *image, const char *name_space, const char *name, MonoError *error)
{
	return mono_exception_new_by_name_domain (mono_domain_get (), image, name_space, name, error);
}
Ejemplo n.º 18
0
Archivo: gc.c Proyecto: Numpsy/mono
/* 
 * actually, we might want to queue the finalize requests in a separate thread,
 * but we need to be careful about the execution domain of the thread...
 */
void
mono_gc_run_finalize (void *obj, void *data)
{
	MonoError error;
	MonoObject *exc = NULL;
	MonoObject *o;
#ifndef HAVE_SGEN_GC
	MonoObject *o2;
#endif
	MonoMethod* finalizer = NULL;
	MonoDomain *caller_domain = mono_domain_get ();
	MonoDomain *domain;
	RuntimeInvokeFunction runtime_invoke;

	// This function is called from the innards of the GC, so our best alternative for now is to do polling here
	mono_threads_safepoint ();

	o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));

	if (mono_do_not_finalize) {
		if (!mono_do_not_finalize_class_names)
			return;

		size_t namespace_len = strlen (o->vtable->klass->name_space);
		for (int i = 0; mono_do_not_finalize_class_names [i]; ++i) {
			const char *name = mono_do_not_finalize_class_names [i];
			if (strncmp (name, o->vtable->klass->name_space, namespace_len))
				break;
			if (name [namespace_len] != '.')
				break;
			if (strcmp (name + namespace_len + 1, o->vtable->klass->name))
				break;
			return;
		}
	}

	if (log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_DEBUG, "<%s at %p> Starting finalizer checks.", o->vtable->klass->name, o);

	if (suspend_finalizers)
		return;

	domain = o->vtable->domain;

#ifndef HAVE_SGEN_GC
	mono_domain_finalizers_lock (domain);

	o2 = (MonoObject *)g_hash_table_lookup (domain->finalizable_objects_hash, o);

	mono_domain_finalizers_unlock (domain);

	if (!o2)
		/* Already finalized somehow */
		return;
#endif

	/* make sure the finalizer is not called again if the object is resurrected */
	object_register_finalizer ((MonoObject *)obj, NULL);

	if (log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Registered finalizer as processed.", o->vtable->klass->name, o);

	if (o->vtable->klass == mono_defaults.internal_thread_class) {
		MonoInternalThread *t = (MonoInternalThread*)o;

		if (mono_gc_is_finalizer_internal_thread (t))
			/* Avoid finalizing ourselves */
			return;

		if (t->threadpool_thread && finalizing_root_domain) {
			/* Don't finalize threadpool threads when
			   shutting down - they're finalized when the
			   threadpool shuts down. */
			if (!add_thread_to_finalize (t, &error))
				goto unhandled_error;
			return;
		}
	}

	if (o->vtable->klass->image == mono_defaults.corlib && !strcmp (o->vtable->klass->name, "DynamicMethod") && finalizing_root_domain) {
		/*
		 * These can't be finalized during unloading/shutdown, since that would
		 * free the native code which can still be referenced by other
		 * finalizers.
		 * FIXME: This is not perfect, objects dying at the same time as 
		 * dynamic methods can still reference them even when !shutdown.
		 */
		return;
	}

	if (mono_runtime_get_no_exec ())
		return;

	/* speedup later... and use a timeout */
	/* g_print ("Finalize run on %p %s.%s\n", o, mono_object_class (o)->name_space, mono_object_class (o)->name); */

	/* Use _internal here, since this thread can enter a doomed appdomain */
	mono_domain_set_internal (mono_object_domain (o));

	/* delegates that have a native function pointer allocated are
	 * registered for finalization, but they don't have a Finalize
	 * method, because in most cases it's not needed and it's just a waste.
	 */
	if (o->vtable->klass->delegate) {
		MonoDelegate* del = (MonoDelegate*)o;
		if (del->delegate_trampoline)
			mono_delegate_free_ftnptr ((MonoDelegate*)o);
		mono_domain_set_internal (caller_domain);
		return;
	}

	finalizer = mono_class_get_finalizer (o->vtable->klass);

	/* If object has a CCW but has no finalizer, it was only
	 * registered for finalization in order to free the CCW.
	 * Else it needs the regular finalizer run.
	 * FIXME: what to do about ressurection and suppression
	 * of finalizer on object with CCW.
	 */
	if (mono_marshal_free_ccw (o) && !finalizer) {
		mono_domain_set_internal (caller_domain);
		return;
	}

	/* 
	 * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (),
	 * create and precompile a wrapper which calls the finalize method using
	 * a CALLVIRT.
	 */
	if (log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o->vtable->klass->name, o);

	if (!domain->finalize_runtime_invoke) {
		MonoMethod *invoke = mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE);

		domain->finalize_runtime_invoke = mono_compile_method_checked (invoke, &error);
		mono_error_assert_ok (&error); /* expect this not to fail */
	}

	runtime_invoke = (RuntimeInvokeFunction)domain->finalize_runtime_invoke;

	mono_runtime_class_init_full (o->vtable, &error);
	if (!is_ok (&error))
		goto unhandled_error;

	if (G_UNLIKELY (MONO_GC_FINALIZE_INVOKE_ENABLED ())) {
		MONO_GC_FINALIZE_INVOKE ((unsigned long)o, mono_object_get_size (o),
				o->vtable->klass->name_space, o->vtable->klass->name);
	}

	if (log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o);

	runtime_invoke (o, NULL, &exc, NULL);

	if (log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o);

unhandled_error:
	if (!is_ok (&error))
		exc = (MonoObject*)mono_error_convert_to_exception (&error);
	if (exc)
		mono_thread_internal_unhandled_exception (exc);

	mono_domain_set_internal (caller_domain);
}
Ejemplo n.º 19
0
/*Can fail with out-of-memory*/
MonoException*
mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
{
	HANDLE_FUNCTION_ENTER ();

	MonoErrorInternal *error = (MonoErrorInternal*)oerror;

	MonoExceptionHandle exception = MONO_HANDLE_CAST (MonoException, mono_new_null ());
	MonoDomain *domain = mono_domain_get ();
	char *type_name = NULL;
	char *message = NULL;

	error_init (error_out);

	const guint16 error_code = error->error_code;

	g_assert (error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);

	switch (error_code) {
	case MONO_ERROR_NONE:
		goto exit;

	case MONO_ERROR_MISSING_METHOD:
		exception = mono_corlib_exception_new_with_args ("System", "MissingMethodException", error->full_message, error->first_argument, error_out);
		break;
	case MONO_ERROR_BAD_IMAGE:
		exception = mono_corlib_exception_new_with_args ("System", "BadImageFormatException", error->full_message, error->first_argument, error_out);
		break;
	case MONO_ERROR_FILE_NOT_FOUND:
		exception = mono_corlib_exception_new_with_args ("System.IO", "FileNotFoundException", error->full_message, error->first_argument, error_out);
		break;
	case MONO_ERROR_MISSING_FIELD:
		exception = mono_corlib_exception_new_with_args ("System", "MissingFieldException", error->full_message, error->first_argument, error_out);
		break;
	case MONO_ERROR_MEMBER_ACCESS:
		exception = mono_exception_new_by_name_msg (mono_defaults.corlib, "System", "MemberAccessException", error->full_message, error_out);
		break;

	case MONO_ERROR_TYPE_LOAD: {
		MonoStringHandle assembly_name;
		MonoStringHandle type_name;

		if ((error->type_name && error->assembly_name) || error->exn.klass) {
			type_name = get_type_name_as_mono_string (error, domain, error_out);
			if (!mono_error_ok (error_out))
				break;

			if (error->assembly_name) {
				assembly_name = string_new_cleanup (domain, error->assembly_name);
				if (MONO_HANDLE_IS_NULL (assembly_name)) {
					mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
					break;
				}
			} else {
				assembly_name = mono_string_empty_handle (domain);
			}

			exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name, error_out);
			if (!MONO_HANDLE_IS_NULL (exception)) {
				const char *full_message = error->full_message;
				if (full_message && full_message [0]) {
					MonoStringHandle msg = string_new_cleanup (mono_domain_get (), full_message);	
					if (!MONO_HANDLE_IS_NULL (msg))
						MONO_HANDLE_SET (exception, message, msg);
					else
						mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
				}
			}
		} else {
			exception = mono_exception_new_by_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message, error_out);
		}
	}
	break;

	case MONO_ERROR_OUT_OF_MEMORY:
		if (domain)
			exception = MONO_HANDLE_NEW (MonoException, domain->out_of_memory_ex);
		if (MONO_HANDLE_IS_NULL (exception))
			exception = mono_get_exception_out_of_memory_handle ();
		break;

	case MONO_ERROR_ARGUMENT:
		exception = mono_exception_new_argument (error->first_argument, error->full_message, error_out);
		break;

	case MONO_ERROR_ARGUMENT_NULL:
		exception = mono_exception_new_argument_null (error->first_argument, error_out);
		break;
	
	case MONO_ERROR_ARGUMENT_OUT_OF_RANGE: 
		exception = mono_exception_new_argument_out_of_range(error->first_argument, error->full_message, error_out); 
		break;

	case MONO_ERROR_NOT_VERIFIABLE:
		if (error->exn.klass) {
			type_name = mono_type_get_full_name (error->exn.klass);
			if (!type_name)
				goto out_of_memory;
		}
		message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, error->full_message);
		if (!message)
			goto out_of_memory;
		exception = mono_exception_new_by_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message, error_out);
		break;

	case MONO_ERROR_GENERIC:
		if (!error->exception_name_space || !error->exception_name)
			mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied");
		else
			exception = mono_exception_new_by_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message, error_out);
		break;

	case MONO_ERROR_EXCEPTION_INSTANCE:
		exception = MONO_HANDLE_CAST (MonoException, mono_gchandle_get_target_handle (error->exn.instance_handle));
		break;

	case MONO_ERROR_CLEANUP_CALLED_SENTINEL:
		mono_error_set_execution_engine (error_out, "MonoError reused after mono_error_cleanup");
		break;

	case MONO_ERROR_INVALID_PROGRAM:
		exception = mono_exception_new_by_name_msg (mono_defaults.corlib, "System", "InvalidProgramException",
			(error->flags & MONO_ERROR_INCOMPLETE) ? "" : error->full_message, error_out);
		break;

	default:
		mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
	}

	if (!mono_error_ok (error_out))
		goto return_null;

	if (MONO_HANDLE_IS_NULL (exception))
		mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
	goto exit;
out_of_memory:
	mono_error_set_out_of_memory (error_out, "Could not allocate message");
	goto exit;
return_null:
	exception = MONO_HANDLE_CAST (MonoException, mono_new_null ());
exit:
	g_free (message);
	g_free (type_name);
	HANDLE_FUNCTION_RETURN_OBJ (exception);
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
0
MonoObject*
ves_icall_System_GC_get_ephemeron_tombstone (void)
{
	return mono_domain_get ()->ephemeron_tombstone;
}
Ejemplo n.º 22
0
void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {

	_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)

	exit_code = -1;

	String logs_dir = GodotSharpDirs::get_build_logs_dir().plus_file(build_info.solution.md5_text() + "_" + build_info.configuration);

	if (build_tab) {
		build_tab->on_build_start();
	} else {
		build_tab = memnew(MonoBuildTab(build_info, logs_dir));
		MonoBottomPanel::get_singleton()->add_build_tab(build_tab);
	}

	if (p_blocking) {
		// Required in order to update the build tasks list
		Main::iteration();
	}

	if (!exited) {
		exited = true;
		String message = "Tried to start build process, but it is already running";
		build_tab->on_build_exec_failed(message);
		ERR_EXPLAIN(message);
		ERR_FAIL();
	}

	exited = false;

	// Remove old issues file

	String issues_file = "msbuild_issues.csv";
	DirAccessRef d = DirAccess::create_for_path(logs_dir);
	if (d->file_exists(issues_file)) {
		Error err = d->remove(issues_file);
		if (err != OK) {
			exited = true;
			String file_path = ProjectSettings::get_singleton()->localize_path(logs_dir).plus_file(issues_file);
			String message = "Cannot remove issues file: " + file_path;
			build_tab->on_build_exec_failed(message);
			ERR_EXPLAIN(message);
			ERR_FAIL();
		}
	}

	GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Build", "BuildInstance");

	MonoObject *mono_object = mono_object_new(mono_domain_get(), klass->get_raw());

	// Construct

	Variant solution = build_info.solution;
	Variant config = build_info.configuration;

	const Variant *ctor_args[2] = { &solution, &config };

	MonoObject *ex = NULL;
	GDMonoMethod *ctor = klass->get_method(".ctor", 2);
	ctor->invoke(mono_object, ctor_args, &ex);

	if (ex) {
		exited = true;
		String message = "The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex);
		build_tab->on_build_exec_failed(message);
		ERR_EXPLAIN(message);
		ERR_FAIL();
	}

	// Call Build

	Variant logger_assembly = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(EDITOR_TOOLS_ASSEMBLY_NAME) + ".dll";
	Variant logger_output_dir = logs_dir;
	Variant custom_props = build_info.custom_props;

	const Variant *args[3] = { &logger_assembly, &logger_output_dir, &custom_props };

	ex = NULL;
	GDMonoMethod *build_method = klass->get_method(p_blocking ? "Build" : "BuildAsync", 3);
	build_method->invoke(mono_object, args, &ex);

	if (ex) {
		exited = true;
		String message = "The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex);
		build_tab->on_build_exec_failed(message);
		ERR_EXPLAIN(message);
		ERR_FAIL();
	}

	// Build returned

	if (p_blocking) {
		exited = true;
		exit_code = klass->get_field("exitCode")->get_int_value(mono_object);

		if (exit_code != 0 && OS::get_singleton()->is_stdout_verbose())
			OS::get_singleton()->print(String("MSBuild finished with exit code " + itos(exit_code) + "\n").utf8());

		build_tab->on_build_exit(exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR);
	} else {
		build_instance = MonoGCHandle::create_strong(mono_object);
		exited = false;
	}
}
MonoBoolean
ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardown, MonoArray **control_chars, int **size)
{
	int dims;

	dims = terminal_get_dimensions ();
	if (dims == -1){
		int cols = 0, rows = 0;
				      
		const char *str = g_getenv ("COLUMNS");
		if (str != NULL)
			cols = atoi (str);
		str = g_getenv ("LINES");
		if (str != NULL)
			rows = atoi (str);

		if (cols != 0 && rows != 0)
			cols_and_lines = (cols << 16) | rows;
		else
			cols_and_lines = -1;
	} else {
		cols_and_lines = dims;
	}
	
	*size = &cols_and_lines;

	/* 17 is the number of entries set in set_control_chars() above.
	 * NCCS is the total size, but, by now, we only care about those 17 values*/
	mono_gc_wbarrier_generic_store (control_chars, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.byte_class, 17));
	if (tcgetattr (STDIN_FILENO, &initial_attr) == -1)
		return FALSE;

	mono_attr = initial_attr;
	mono_attr.c_lflag &= ~(ICANON);
	mono_attr.c_iflag &= ~(IXON|IXOFF);
	mono_attr.c_cc [VMIN] = 1;
	mono_attr.c_cc [VTIME] = 0;
#ifdef VDSUSP
	/* Disable C-y being used as a suspend character on OSX */
	mono_attr.c_cc [VDSUSP] = 255;
#endif
	if (tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr) == -1)
		return FALSE;

	set_control_chars (*control_chars, mono_attr.c_cc);
	/* If initialized from another appdomain... */
	if (setup_finished)
		return TRUE;

	keypad_xmit_str = keypad != NULL ? mono_string_to_utf8 (keypad) : NULL;
	
	console_set_signal_handlers ();
	setup_finished = TRUE;
	if (!atexit_called) {
		if (teardown != NULL)
			teardown_str = mono_string_to_utf8 (teardown);

		mono_atexit (tty_teardown);
	}

	return TRUE;
}
Ejemplo n.º 24
0
static void
suspend_thread (SgenThreadInfo *info, void *context)
{
	int stop_count;
#ifndef USE_MONO_CTX
	gpointer regs [ARCH_NUM_REGS];
#endif
	MonoContext ctx;
	gpointer stack_start;

	info->client_info.stopped_domain = mono_domain_get ();
	info->client_info.signal = 0;
	stop_count = sgen_global_stop_count;
	/* duplicate signal */
	if (0 && info->client_info.stop_count == stop_count)
		return;

#ifdef USE_MONO_CTX
	if (context) {
		mono_sigctx_to_monoctx (context, &ctx);
		info->client_info.stopped_ip = MONO_CONTEXT_GET_IP (&ctx);
		stack_start = (((guint8 *) MONO_CONTEXT_GET_SP (&ctx)) - REDZONE_SIZE);
	} else {
		info->client_info.stopped_ip = NULL;
		stack_start = NULL;
	}
#else
	info->client_info.stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL;
	stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL;
#endif

	/* If stack_start is not within the limits, then don't set it
	   in info and we will be restarted. */
	if (stack_start >= info->client_info.stack_start_limit && stack_start <= info->client_info.stack_end) {
		info->client_info.stack_start = stack_start;

#ifdef USE_MONO_CTX
		if (context) {
			memcpy (&info->client_info.ctx, &ctx, sizeof (MonoContext));
		} else {
			memset (&info->client_info.ctx, 0, sizeof (MonoContext));
		}
#else
		if (context) {
			ARCH_COPY_SIGCTX_REGS (regs, context);
			memcpy (&info->client_info.regs, regs, sizeof (info->client_info.regs));
		} else {
			memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
		}
#endif
	} else {
		g_assert (!info->client_info.stack_start);
	}

	/* Notify the JIT */
	if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
		mono_gc_get_gc_callbacks ()->thread_suspend_func (info->client_info.runtime_data, context, NULL);

	SGEN_LOG (4, "Posting suspend_ack_semaphore for suspend from %p %p", info, (gpointer) (gsize) mono_native_thread_id_get ());

	/*
	Block the restart signal. 
	We need to block the restart signal while posting to the suspend_ack semaphore or we race to sigsuspend,
	which might miss the signal and get stuck.
	*/
	pthread_sigmask (SIG_BLOCK, &suspend_ack_signal_mask, NULL);

	/* notify the waiting thread */
	SGEN_SEMAPHORE_POST (suspend_ack_semaphore_ptr);
	info->client_info.stop_count = stop_count;

	/* wait until we receive the restart signal */
	do {
		info->client_info.signal = 0;
		sigsuspend (&suspend_signal_mask);
	} while (info->client_info.signal != restart_signal_num);

	/* Unblock the restart signal. */
	pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL);

	SGEN_LOG (4, "Posting suspend_ack_semaphore for resume from %p %p\n", info, (gpointer) (gsize) mono_native_thread_id_get ());
	/* notify the waiting thread */
	SGEN_SEMAPHORE_POST (suspend_ack_semaphore_ptr);
}
Ejemplo n.º 25
0
/**
 * mono_exception_from_name:
 * @image: the Mono image where to look for the class
 * @name_space: the namespace for the class
 * @name: class name
 *
 * Creates an exception of the given namespace/name class in the
 * current domain.
 *
 * Returns: the initialized exception instance.
 */
MonoException *
mono_exception_from_name (MonoImage *image, const char *name_space,
			  const char *name)
{
	return mono_exception_from_name_domain (mono_domain_get (), image, name_space, name);
}
Ejemplo n.º 26
0
static MonoString*
gimme () {
	return mono_string_new (mono_domain_get (), "All your monos are belong to us!");
}
Ejemplo n.º 27
0
/*
 * mini_add_method_trampoline:
 *
 *   Add static rgctx/gsharedvt_in trampoline to M/COMPILED_METHOD if needed. Return the trampoline address, or
 * COMPILED_METHOD if no trampoline is needed.
 * ORIG_METHOD is the method the caller originally called i.e. an iface method, or NULL.
 */
gpointer
mini_add_method_trampoline (MonoMethod *orig_method, MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp)
{
	gpointer addr = compiled_method;
	gboolean callee_gsharedvt, callee_array_helper;
	MonoJitInfo *ji = 
		mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method), NULL);

	// FIXME: This loads information from AOT
	callee_gsharedvt = ji_is_gsharedvt (ji);

	callee_array_helper = FALSE;
	if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
		WrapperInfo *info = mono_marshal_get_wrapper_info (m);

		/*
		 * generic array helpers.
		 * Have to replace the wrappers with the original generic instances.
		 */
		if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) {
			callee_array_helper = TRUE;
			m = info->d.generic_array_helper.method;
		}
	} else if (m->wrapper_type == MONO_WRAPPER_UNKNOWN) {
		WrapperInfo *info = mono_marshal_get_wrapper_info (m);

		/* Same for synchronized inner wrappers */
		if (info && info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
			m = info->d.synchronized_inner.method;
		}
	}

	if (!orig_method)
		orig_method = m;

	if (callee_gsharedvt)
		g_assert (m->is_inflated);

	addr = compiled_method;

	if (callee_gsharedvt && mini_is_gsharedvt_variable_signature (mono_method_signature (ji->method))) {
		MonoGenericSharingContext *gsctx;
		MonoMethodSignature *sig, *gsig;

		/* Here m is a generic instance, while ji->method is the gsharedvt method implementing it */

		/* Call from normal/gshared code to gsharedvt code with variable signature */
		gsctx = mono_jit_info_get_generic_sharing_context (ji);

		sig = mono_method_signature (m);
		gsig = mono_method_signature (ji->method); 

		addr = mini_get_gsharedvt_wrapper (TRUE, compiled_method, sig, gsig, gsctx, -1, FALSE);

		//printf ("IN: %s\n", mono_method_full_name (m, TRUE));
	}

	if (add_static_rgctx_tramp && !callee_array_helper)
		addr = mono_create_static_rgctx_trampoline (m, addr);

	return addr;
}
Ejemplo n.º 28
0
MonoBoolean
ves_icall_System_Globalization_CalendarData_fill_calendar_data (MonoCalendarData *this_obj, MonoString *name, gint32 calendar_index)
{
	MonoError error;
	MonoDomain *domain;
	const DateTimeFormatEntry *dfe;
	const CultureInfoNameEntry *ne;
	const CultureInfoEntry *ci;
	char *n;

	n = mono_string_to_utf8_checked (name, &error);
	if (mono_error_set_pending_exception (&error))
		return FALSE;
	ne = (const CultureInfoNameEntry *)mono_binary_search (n, culture_name_entries, NUM_CULTURE_ENTRIES,
			sizeof (CultureInfoNameEntry), culture_name_locator);
	g_free (n);
	if (ne == NULL) {
		return FALSE;
	}

	ci = &culture_entries [ne->culture_entry_index];
	dfe = &datetime_format_entries [ci->datetime_format_index];

	domain = mono_domain_get ();

	MONO_OBJECT_SETREF (this_obj, NativeName, mono_string_new (domain, idx2string (ci->nativename)));
	MonoArray *short_date_patterns = create_names_array_idx_dynamic (dfe->short_date_patterns,
									 NUM_SHORT_DATE_PATTERNS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, ShortDatePatterns, short_date_patterns);
	MonoArray *year_month_patterns =create_names_array_idx_dynamic (dfe->year_month_patterns,
									NUM_YEAR_MONTH_PATTERNS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, YearMonthPatterns, year_month_patterns);

	MonoArray *long_date_patterns = create_names_array_idx_dynamic (dfe->long_date_patterns,
									NUM_LONG_DATE_PATTERNS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, LongDatePatterns, long_date_patterns);

	MONO_OBJECT_SETREF (this_obj, MonthDayPattern, mono_string_new (domain, pattern2string (dfe->month_day_pattern)));

	MonoArray *day_names = create_names_array_idx (dfe->day_names, NUM_DAYS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, DayNames, day_names);

	MonoArray *abbr_day_names = create_names_array_idx (dfe->abbreviated_day_names, 
							    NUM_DAYS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, AbbreviatedDayNames, abbr_day_names);

	MonoArray *ss_day_names = create_names_array_idx (dfe->shortest_day_names, NUM_DAYS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, SuperShortDayNames, ss_day_names);

	MonoArray *month_names = create_names_array_idx (dfe->month_names, NUM_MONTHS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, MonthNames, month_names);

	MonoArray *abbr_mon_names = create_names_array_idx (dfe->abbreviated_month_names,
							    NUM_MONTHS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, AbbreviatedMonthNames, abbr_mon_names);

	
	MonoArray *gen_month_names = create_names_array_idx (dfe->month_genitive_names, NUM_MONTHS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, GenitiveMonthNames, gen_month_names);

	MonoArray *gen_abbr_mon_names = create_names_array_idx (dfe->abbreviated_month_genitive_names, NUM_MONTHS, &error);
	return_val_and_set_pending_if_nok (&error, FALSE);
	MONO_OBJECT_SETREF (this_obj, GenitiveAbbreviatedMonthNames, gen_abbr_mon_names);

	return TRUE;
}
Ejemplo n.º 29
0
void
ves_icall_System_Globalization_CultureInfo_construct_datetime_format (MonoCultureInfo *this)
{
	MonoDomain *domain;
	MonoDateTimeFormatInfo *datetime;
	const DateTimeFormatEntry *dfe;

	MONO_ARCH_SAVE_REGS;

	g_assert (this->datetime_index >= 0);

	datetime = this->datetime_format;
	dfe = &datetime_format_entries [this->datetime_index];

	domain = mono_domain_get ();

	datetime->readOnly = this->is_read_only;
	MONO_OBJECT_SETREF (datetime, AbbreviatedDayNames, create_names_array_idx (dfe->abbreviated_day_names,
			NUM_DAYS));
	MONO_OBJECT_SETREF (datetime, AbbreviatedMonthNames, create_names_array_idx (dfe->abbreviated_month_names,
			NUM_MONTHS));
	MONO_OBJECT_SETREF (datetime, AMDesignator, mono_string_new (domain, idx2string (dfe->am_designator)));
	datetime->CalendarWeekRule = dfe->calendar_week_rule;
	MONO_OBJECT_SETREF (datetime, DateSeparator, mono_string_new (domain, idx2string (dfe->date_separator)));
	MONO_OBJECT_SETREF (datetime, DayNames, create_names_array_idx (dfe->day_names, NUM_DAYS));
	datetime->FirstDayOfWeek = dfe->first_day_of_week;
	MONO_OBJECT_SETREF (datetime, FullDateTimePattern, mono_string_new (domain, idx2string (dfe->full_date_time_pattern)));
	MONO_OBJECT_SETREF (datetime, LongDatePattern, mono_string_new (domain, idx2string (dfe->long_date_pattern)));
	MONO_OBJECT_SETREF (datetime, LongTimePattern, mono_string_new (domain, idx2string (dfe->long_time_pattern)));
	MONO_OBJECT_SETREF (datetime, MonthDayPattern, mono_string_new (domain, idx2string (dfe->month_day_pattern)));
Ejemplo n.º 30
0
MonoArray*
ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral,
		MonoBoolean specific, MonoBoolean installed)
{
	MonoError error;
	MonoArray *ret;
	MonoClass *klass;
	MonoCultureInfo *culture;
	MonoDomain *domain;
	const CultureInfoEntry *ci;
	gint i, len;
	gboolean is_neutral;

	domain = mono_domain_get ();

	len = 0;
	for (i = 0; i < NUM_CULTURE_ENTRIES; i++) {
		ci = &culture_entries [i];
		is_neutral = ci->territory == 0;
		if ((neutral && is_neutral) || (specific && !is_neutral))
			len++;
	}

	klass = mono_class_get_culture_info_class ();

	/* The InvariantCulture is not in culture_entries */
	/* We reserve the first slot in the array for it */
	if (neutral)
		len++;

	ret = mono_array_new_checked (domain, klass, len, &error);
	if (!is_ok (&error))
		goto fail;

	if (len == 0)
		return ret;

	len = 0;
	if (neutral)
		mono_array_setref (ret, len++, NULL);

	for (i = 0; i < NUM_CULTURE_ENTRIES; i++) {
		ci = &culture_entries [i];
		is_neutral = ci->territory == 0;
		if ((neutral && is_neutral) || (specific && !is_neutral)) {
			culture = (MonoCultureInfo *) mono_object_new_checked (domain, klass, &error);
			if (!is_ok (&error)) goto fail;
			mono_runtime_object_init_checked ((MonoObject *) culture, &error);
			if (!is_ok (&error)) goto fail;
			if (!construct_culture (culture, ci, &error))
				goto fail;
			culture->use_user_override = TRUE;
			mono_array_setref (ret, len++, culture);
		}
	}

	return ret;

fail:
	mono_error_set_pending_exception (&error);
	return ret;
}