[marshal] Rethrow in native-to-managed wrapper to keep exception stacktrace (#5384)
[mono.git] / mono / metadata / marshal.c
index 25fc058351e36735ff650c4dc7609040bcaaf118..63358bf3baff17983faf525d7d4c0fe1c9d5b5b1 100644 (file)
@@ -799,12 +799,13 @@ mono_array_to_lparray (MonoArray *array)
 
        int i = 0;
        MonoClass *klass;
+       MonoError error;
 #endif
 
        if (!array)
                return NULL;
 #ifndef DISABLE_COM
-
+       error_init (&error);
        klass = array->obj.vtable->klass;
 
        switch (klass->element_class->byval_arg.type) {
@@ -813,9 +814,12 @@ mono_array_to_lparray (MonoArray *array)
                break;
        case MONO_TYPE_CLASS:
                nativeArraySize = array->max_length;
-               nativeArray = (void **)malloc(sizeof(gpointer) * nativeArraySize);
-               for(i = 0; i < nativeArraySize; ++i)    
-                       nativeArray[i] = ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal(((MonoObject **)array->vector)[i]);
+               nativeArray = (void **)g_malloc (sizeof(gpointer) * nativeArraySize);
+               for(i = 0; i < nativeArraySize; ++i) {
+                       nativeArray[i] = mono_cominterop_get_com_interface (((MonoObject **)array->vector)[i], klass->element_class, &error);
+                       if (mono_error_set_pending_exception (&error))
+                               break;
+               }
                return nativeArray;
        case MONO_TYPE_U1:
        case MONO_TYPE_BOOLEAN:
@@ -853,7 +857,6 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray)
 {
 #ifndef DISABLE_COM
        MonoClass *klass;
-       int i = 0;
 
        if (!array)
                return;
@@ -862,11 +865,8 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray)
                return;
        klass = array->obj.vtable->klass;
 
-       if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) {
-               for(i = 0; i < array->max_length; ++i)
-                       mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i));
+       if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS)
                g_free (nativeArray);
-       }
 #endif
 }
 
@@ -4416,7 +4416,7 @@ mono_marshal_get_runtime_invoke_full (MonoMethod *method, gboolean virtual_, gbo
        csig->call_convention = MONO_CALL_C;
 #endif
 
-       name = mono_signature_to_name (callsig, virtual_ ? "runtime_invoke_virtual" : "runtime_invoke");
+       name = mono_signature_to_name (callsig, virtual_ ? "runtime_invoke_virtual" : (need_direct_wrapper ? "runtime_invoke_direct" : "runtime_invoke"));
        mb = mono_mb_new (target_klass, name,  MONO_WRAPPER_RUNTIME_INVOKE);
        g_free (name);
 
@@ -4483,6 +4483,9 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_)
        if (virtual_)
                need_direct_wrapper = TRUE;
 
+       if (method->dynamic)
+               need_direct_wrapper = TRUE;
+
        if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
                (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
                /*
@@ -7692,7 +7695,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
                mono_mb_add_local (mb, sig->ret);
        }
 
-       if (mono_threads_is_coop_enabled ()) {
+       if (mono_threads_is_blocking_transition_enabled ()) {
                /* local 4, dummy local used to get a stack address for suspend funcs */
                coop_gc_stack_dummy = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
                /* local 5, the local to be used when calling the suspend funcs */
@@ -7733,7 +7736,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        }
 
        // In coop mode need to register blocking state during native call
-       if (mono_threads_is_coop_enabled ()) {
+       if (mono_threads_is_blocking_transition_enabled ()) {
                // Perform an extra, early lookup of the function address, so any exceptions
                // potentially resulting from the lookup occur before entering blocking mode.
                if (!func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass) && aot) {
@@ -7818,7 +7821,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        }
 
        /* Unblock before converting the result, since that can involve calls into the runtime */
-       if (mono_threads_is_coop_enabled ()) {
+       if (mono_threads_is_blocking_transition_enabled ()) {
                mono_mb_emit_ldloc (mb, coop_gc_var);
                mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
                mono_mb_emit_icall (mb, mono_threads_exit_gc_safe_region_unbalanced);
@@ -8587,7 +8590,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        /* try { */
        clause_catch->try_offset = clause_finally->try_offset = mono_mb_get_label (mb);
 
-       if (!mono_threads_is_coop_enabled ()) {
+       if (!mono_threads_is_blocking_transition_enabled ()) {
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
        } else {
@@ -8769,7 +8772,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset;
        clause_finally->handler_offset = mono_mb_get_label (mb);
 
-       if (!mono_threads_is_coop_enabled ()) {
+       if (!mono_threads_is_blocking_transition_enabled ()) {
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
        } else {
@@ -11587,7 +11590,6 @@ mono_marshal_load_type_info (MonoClass* klass)
 
        layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
 
-       /* The mempool is protected by the loader lock */
        info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
        info->num_fields = count;
        
@@ -11674,8 +11676,11 @@ mono_marshal_load_type_info (MonoClass* klass)
        info->min_align = min_align;
 
        /* Update the class's blittable info, if the layouts don't match */
-       if (info->native_size != mono_class_value_size (klass, NULL))
+       if (info->native_size != mono_class_value_size (klass, NULL)) {
+               mono_loader_lock ();
                klass->blittable = FALSE;
+               mono_loader_unlock ();
+       }
 
        /* If this is an array type, ensure that we have element info */
        if (klass->rank && !mono_marshal_is_loading_type_info (klass->element_class)) {
@@ -12361,7 +12366,7 @@ ftnptr_eh_callback_default (guint32 gchandle)
 
        mono_gchandle_free (gchandle);
 
-       mono_raise_exception (exc);
+       mono_reraise_exception (exc);
 }
 
 /*