Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / remoting.c
index aee1b27ca833f4bf7646a6627711920bfcb09de8..dccb077b4f72cc41ccf1b0a47e9dee452794ad3d 100644 (file)
@@ -21,6 +21,7 @@
 #include "mono/metadata/exception.h"
 #include "mono/metadata/debug-helpers.h"
 #include "mono/metadata/reflection-internals.h"
+#include "mono/metadata/assembly.h"
 
 typedef enum {
        MONO_MARSHAL_NONE,                      /* No marshalling needed */
@@ -52,6 +53,9 @@ typedef struct _MonoRemotingMethods MonoRemotingMethods;
 static MonoObject *
 mono_remoting_wrapper (MonoMethod *method, gpointer *params);
 
+static MonoException *
+mono_remoting_update_exception (MonoException *exc);
+
 static gint32
 mono_marshal_set_domain_by_id (gint32 id, MonoBoolean push);
 
@@ -70,6 +74,13 @@ mono_marshal_xdomain_copy_out_value (MonoObject *src, MonoObject *dst);
 static MonoReflectionType *
 type_from_handle (MonoType *handle);
 
+static void
+mono_context_set_icall (MonoAppContext *new_context);
+
+static MonoAppContext*
+mono_context_get_icall (void);
+
+
 /* Class lazy loading functions */
 static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, "System.Runtime.Remoting", "RemotingServices")
 static GENERATE_GET_CLASS_WITH_CACHE (call_context, "System.Runtime.Remoting.Messaging", "CallContext")
@@ -199,12 +210,16 @@ mono_remoting_marshal_init (void)
                register_icall (ves_icall_mono_marshal_xdomain_copy_value, "ves_icall_mono_marshal_xdomain_copy_value", "object object", FALSE);
                register_icall (mono_marshal_xdomain_copy_out_value, "mono_marshal_xdomain_copy_out_value", "void object object", FALSE);
                register_icall (mono_remoting_wrapper, "mono_remoting_wrapper", "object ptr ptr", FALSE);
+               register_icall (mono_remoting_update_exception, "mono_remoting_update_exception", "object object", FALSE);
                register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
 
 #ifndef DISABLE_JIT
                register_icall (mono_compile_method_icall, "mono_compile_method_icall", "ptr ptr", FALSE);
 #endif
 
+               register_icall (mono_context_get_icall, "mono_context_get_icall", "object", FALSE);
+               register_icall (mono_context_set_icall, "mono_context_set_icall", "void object", FALSE);
+
        }
 
        icalls_registered = TRUE;
@@ -415,6 +430,7 @@ mono_remoting_wrapper (MonoMethod *method, gpointer *params)
 
        if (exc) {
                error_init (&error);
+               exc = (MonoObject*) mono_remoting_update_exception ((MonoException*)exc);
                mono_error_set_exception_instance (&error, (MonoException *)exc);
                goto fail;
        }
@@ -434,6 +450,37 @@ fail:
        return NULL;
 } 
 
+/*
+ * Handles exception transformation at appdomain call boundary.
+ * Note this is called from target appdomain inside xdomain wrapper, but from
+ * source domain in the mono_remoting_wrapper slowpath.
+ */
+static MonoException *
+mono_remoting_update_exception (MonoException *exc)
+{
+       MonoInternalThread *thread;
+       MonoClass *klass = mono_object_get_class ((MonoObject*)exc);
+
+       /* Serialization error can only happen when still in the target appdomain */
+       if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SERIALIZABLE)) {
+               MonoException *ret;
+               char *aname = mono_stringify_assembly_name (&klass->image->assembly->aname);
+               char *message = g_strdup_printf ("Type '%s' in Assembly '%s' is not marked as serializable", klass->name, aname);
+               ret =  mono_get_exception_serialization (message);
+               g_free (aname);
+               g_free (message);
+               return ret;
+       }
+
+       thread = mono_thread_internal_current ();
+       if (mono_object_get_class ((MonoObject*)exc) == mono_defaults.threadabortexception_class &&
+                       thread->flags & MONO_THREAD_FLAG_APPDOMAIN_ABORT) {
+               mono_thread_internal_reset_abort (thread);
+               return mono_get_exception_appdomain_unloaded ();
+       }
+
+       return exc;
+}
 
 /**
  * mono_marshal_get_remoting_invoke:
@@ -884,15 +931,18 @@ mono_marshal_get_xappdomain_dispatch (MonoMethod *method, int *marshal_types, in
        
        /* handler code */
        main_clause->handler_offset = mono_mb_get_label (mb);
+
+       mono_mb_emit_icall (mb, mono_remoting_update_exception);
+       mono_mb_emit_op (mb, CEE_CASTCLASS, mono_defaults.exception_class);
        mono_mb_emit_managed_call (mb, method_rs_serialize_exc, NULL);
        mono_mb_emit_stloc (mb, loc_serialized_exc);
        mono_mb_emit_ldarg (mb, 2);
        mono_mb_emit_ldloc (mb, loc_serialized_exc);
        mono_mb_emit_byte (mb, CEE_STIND_REF);
        mono_mb_emit_branch (mb, CEE_LEAVE);
+
        main_clause->handler_len = mono_mb_get_pos (mb) - main_clause->handler_offset;
        /* end catch */
-
        mono_mb_patch_branch (mb, pos_leave);
        
        if (copy_return)
@@ -996,7 +1046,7 @@ mono_marshal_get_xappdomain_invoke (MonoMethod *method)
 
        /* Save thread domain data */
 
-       mono_mb_emit_icall (mb, mono_context_get);
+       mono_mb_emit_icall (mb, mono_context_get_icall);
        mono_mb_emit_byte (mb, CEE_DUP);
        mono_mb_emit_stloc (mb, loc_context);
 
@@ -1137,7 +1187,7 @@ mono_marshal_get_xappdomain_invoke (MonoMethod *method)
        /* Restore thread domain data */
        
        mono_mb_emit_ldloc (mb, loc_context);
-       mono_mb_emit_icall (mb, mono_context_set);
+       mono_mb_emit_icall (mb, mono_context_set_icall);
        
        /* if (loc_serialized_exc != null) ... */
 
@@ -1593,7 +1643,7 @@ mono_marshal_get_ldflda_wrapper (MonoType *type)
        mono_mb_emit_byte (mb, CEE_LDIND_REF);
        mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, context));
        mono_mb_emit_byte (mb, CEE_LDIND_REF);
-       mono_mb_emit_icall (mb, mono_context_get);
+       mono_mb_emit_icall (mb, mono_context_get_icall);
        pos3 = mono_mb_emit_branch (mb, CEE_BEQ);
 
        mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another context.");
@@ -2050,3 +2100,20 @@ ves_icall_mono_marshal_xdomain_copy_value (MonoObject *val)
        mono_error_set_pending_exception (&error);
        return result;
 }
+
+void
+mono_context_set_icall (MonoAppContext *new_context_raw)
+{
+       HANDLE_FUNCTION_ENTER ();
+       MONO_HANDLE_DCL (MonoAppContext, new_context);
+       mono_context_set_handle (new_context);
+       HANDLE_FUNCTION_RETURN ();
+}
+
+static MonoAppContext* 
+mono_context_get_icall (void)
+{
+       HANDLE_FUNCTION_ENTER ();
+       MonoAppContextHandle context = mono_context_get_handle ();
+       HANDLE_FUNCTION_RETURN_OBJ (context);
+}