Merge pull request #3042 from lambdageek/dev/monoerror-upgrade_remote_class
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 25 May 2016 14:12:25 +0000 (10:12 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 25 May 2016 14:12:25 +0000 (10:12 -0400)
[remoting] Pass MonoError to mono_upgrade_remote_class

mono/metadata/class-internals.h
mono/metadata/icall.c
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/remoting.c
mono/mini/mini-runtime.c

index 1e7404d4e0ca4f35fa84f5ce47c475a9b3694ef0..dcd856692c28b2d71ab285e5d336f2118cffd8be 100644 (file)
@@ -905,7 +905,7 @@ typedef struct {
 
 extern MonoStats mono_stats;
 
-typedef gpointer (*MonoRemotingTrampoline)       (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target);
+typedef gpointer (*MonoRemotingTrampoline)       (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error);
 typedef gpointer (*MonoDelegateTrampoline)       (MonoDomain *domain, MonoClass *klass);
 
 typedef gboolean (*MonoGetCachedClassInfo) (MonoClass *klass, MonoCachedClassInfo *res);
index 3209e136f8baf9310788384444a02ccac004cff0..8d13d5c5d53f9ee22aa857169c83b67b156711e5 100644 (file)
@@ -6733,17 +6733,15 @@ ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoStri
        }
 
        tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
-       if (!is_ok (&error)) {
-               mono_error_set_pending_exception (&error);
+       if (mono_error_set_pending_exception (&error))
                return NULL;
-       }
        tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
-       if (!is_ok (&error)) {
-               mono_error_set_pending_exception (&error);
+       if (mono_error_set_pending_exception (&error))
                return NULL;
-       }
 
-       res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
+       res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
        return res;
 }
 
index 659bd648289bce6e49f27ff059b02e2462019ee5..8c727448a2d5449c4b960f2f586c79ba7efc753e 100644 (file)
@@ -1447,10 +1447,10 @@ MonoObject *
 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject **exc, MonoArray **out_args, MonoError *error);
 
 gpointer
-mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *real_proxy);
+mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *real_proxy, MonoError *error);
 
-void
-mono_upgrade_remote_class (MonoDomain *domain, MonoObject *tproxy, MonoClass *klass);
+gboolean
+mono_upgrade_remote_class (MonoDomain *domain, MonoObject *tproxy, MonoClass *klass, MonoError *error);
 
 void*
 mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, void **res, MonoError *error);
index eb7738bf45ac94a5ee17c4d852c41da9c5df8e8f..00d225552b6fac77c2070bbf59232d4139b4eea6 100644 (file)
@@ -541,7 +541,7 @@ mono_release_type_locks (MonoInternalThread *thread)
 #ifndef DISABLE_REMOTING
 
 static gpointer
-default_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target)
+default_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
 {
        g_error ("remoting not installed");
        return NULL;
@@ -2305,25 +2305,27 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro
  * mono_class_proxy_vtable:
  * @domain: the application domain
  * @remove_class: the remote class
+ * @error: set on error
  *
  * Creates a vtable for transparent proxies. It is basically
  * a copy of the real vtable of the class wrapped in @remote_class,
  * but all function pointers invoke the remoting functions, and
  * vtable->klass points to the transparent proxy class, and not to @class.
+ *
+ * On failure returns NULL and sets @error
  */
 static MonoVTable *
-mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
+mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
        MonoVTable *vt, *pvt;
        int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
        MonoClass *k;
        GSList *extra_interfaces = NULL;
        MonoClass *klass = remote_class->proxy_class;
        gpointer *interface_offsets;
-       uint8_t *bitmap;
+       uint8_t *bitmap = NULL;
        int bsize;
        size_t imt_table_bytes;
        
@@ -2331,6 +2333,8 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        int bcsize;
 #endif
 
+       mono_error_init (error);
+
        vt = mono_class_vtable (domain, klass);
        g_assert (vt); /*FIXME property handle failure*/
        max_interface_id = vt->max_interface_id;
@@ -2351,8 +2355,9 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                
                method_count = mono_class_num_methods (iclass);
        
-               ifaces = mono_class_get_implemented_interfaces (iclass, &error);
-               g_assert (mono_error_ok (&error)); /*FIXME do proper error handling*/
+               ifaces = mono_class_get_implemented_interfaces (iclass, error);
+               if (!is_ok (error))
+                       goto failure;
                if (ifaces) {
                        for (i = 0; i < ifaces->len; ++i) {
                                MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
@@ -2365,6 +2370,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                                method_count += mono_class_num_methods (ic);
                        }
                        g_ptr_array_free (ifaces, TRUE);
+                       ifaces = NULL;
                }
 
                extra_interface_vtsize += method_count * sizeof (gpointer);
@@ -2394,9 +2400,11 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        for (i = 0; i < klass->vtable_size; ++i) {
                MonoMethod *cm;
                    
-               if ((cm = klass->vtable [i]))
-                       pvt->vtable [i] = arch_create_remoting_trampoline (domain, cm, target_type);
-               else
+               if ((cm = klass->vtable [i])) {
+                       pvt->vtable [i] = arch_create_remoting_trampoline (domain, cm, target_type, error);
+                       if (!is_ok (error))
+                               goto failure;
+               } else
                        pvt->vtable [i] = NULL;
        }
 
@@ -2406,8 +2414,11 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                        MonoMethod* m;
                        gpointer iter = NULL;
                        while ((m = mono_class_get_methods (k, &iter)))
-                               if (!pvt->vtable [m->slot])
-                                       pvt->vtable [m->slot] = arch_create_remoting_trampoline (domain, m, target_type);
+                               if (!pvt->vtable [m->slot]) {
+                                       pvt->vtable [m->slot] = arch_create_remoting_trampoline (domain, m, target_type, error);
+                                       if (!is_ok (error))
+                                               goto failure;
+                               }
                }
        }
 
@@ -2439,8 +2450,11 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
 
                        iter = NULL;
                        j = 0;
-                       while ((cm = mono_class_get_methods (interf, &iter)))
-                               pvt->vtable [slot + j++] = arch_create_remoting_trampoline (domain, cm, target_type);
+                       while ((cm = mono_class_get_methods (interf, &iter))) {
+                               pvt->vtable [slot + j++] = arch_create_remoting_trampoline (domain, cm, target_type, error);
+                               if (!is_ok (error))
+                                       goto failure;
+                       }
                        
                        slot += mono_class_num_methods (interf);
                }
@@ -2461,6 +2475,13 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        pvt->interface_bitmap = bitmap;
 #endif
        return pvt;
+failure:
+       if (extra_interfaces)
+               g_slist_free (extra_interfaces);
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       g_free (bitmap);
+#endif
+       return NULL;
 }
 
 #endif /* DISABLE_REMOTING */
@@ -2726,17 +2747,20 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass
 }
 
 gpointer
-mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
+mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
+
        mono_loader_lock (); /*FIXME mono_class_from_mono_type and mono_class_proxy_vtable take it*/
        mono_domain_lock (domain);
        if (rp->target_domain_id != -1) {
                if (remote_class->xdomain_vtable == NULL)
-                       remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
+                       remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN, error);
                mono_domain_unlock (domain);
                mono_loader_unlock ();
+               return_val_if_nok (error, NULL);
                return remote_class->xdomain_vtable;
        }
        if (remote_class->default_vtable == NULL) {
@@ -2746,10 +2770,16 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
                klass = mono_class_from_mono_type (type);
 #ifndef DISABLE_COM
                if ((mono_class_is_com_object (klass) || (mono_class_get_com_object_class () && klass == mono_class_get_com_object_class ())) && !mono_vtable_is_remote (mono_class_vtable (mono_domain_get (), klass)))
-                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
+                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP, error);
                else
 #endif
-                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
+                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN, error);
+               /* N.B. both branches of the if modify error */
+               if (!is_ok (error)) {
+                       mono_domain_unlock (domain);
+                       mono_loader_unlock ();
+                       return NULL;
+               }
        }
        
        mono_domain_unlock (domain);
@@ -2762,13 +2792,14 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
  * @domain: the application domain
  * @tproxy: the proxy whose remote class has to be upgraded.
  * @klass: class to which the remote class can be casted.
+ * @error: set on error
  *
  * Updates the vtable of the remote class by adding the necessary method slots
  * and interface offsets so it can be safely casted to klass. klass can be a
- * class or an interface.
+ * class or an interface.  On success returns TRUE, on failure returns FALSE and sets @error.
  */
-void
-mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
+gboolean
+mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -2776,6 +2807,7 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoCla
        MonoRemoteClass *remote_class;
        gboolean redo_vtable;
 
+       mono_error_init (error);
        mono_loader_lock (); /*FIXME mono_remote_class_vtable requires it.*/
        mono_domain_lock (domain);
 
@@ -2795,11 +2827,15 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoCla
 
        if (redo_vtable) {
                tproxy->remote_class = clone_remote_class (domain, remote_class, klass);
-               proxy_object->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp);
+               proxy_object->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp, error);
+               if (!is_ok (error))
+                       goto leave;
        }
        
+leave:
        mono_domain_unlock (domain);
        mono_loader_unlock ();
+       return is_ok (error);
 }
 #endif /* DISABLE_REMOTING */
 
@@ -6505,7 +6541,8 @@ mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError
 
                if (*(MonoBoolean *) mono_object_unbox(res)) {
                        /* Update the vtable of the remote type, so it can safely cast to this new type */
-                       mono_upgrade_remote_class (domain, obj, klass);
+                       mono_upgrade_remote_class (domain, obj, klass, error);
+                       return_val_if_nok (error, NULL);
                        return obj;
                }
        }
index 6e09671dac420ab0e68a7a4b2a2e080f1cac01f6..0afdec6960aa7987fbb77a2c5dc26d6cb18aeb6e 100644 (file)
@@ -1967,10 +1967,12 @@ mono_marshal_get_proxy_cancast (MonoClass *klass)
 void
 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
 {
+       MonoError error;
        MonoClass *klass;
        MonoDomain *domain = ((MonoObject*)tproxy)->vtable->domain;
        klass = mono_class_from_mono_type (rtype->type);
-       mono_upgrade_remote_class (domain, (MonoObject*)tproxy, klass);
+       mono_upgrade_remote_class (domain, (MonoObject*)tproxy, klass, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 #else /* DISABLE_REMOTING */
index 717e97f0669f7fb7fdb47b5f9c0cfa9ce3c38d63..b1cb79734d5b607f96df20034f6f866da27c07d9 100644 (file)
@@ -2890,27 +2890,25 @@ MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
  * Returns: a pointer to the newly created code
  */
 static gpointer
-mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target)
+mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
 {
-       MonoError error;
        MonoMethod *nm;
        guint8 *addr = NULL;
 
+       mono_error_init (error);
+
        if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) {
                return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
                        domain, NULL);
        }
 
        if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
-           (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))) {
+           (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class)))
                nm = mono_marshal_get_remoting_invoke_for_target (method, target);
-               addr = (guint8 *)mono_compile_method_checked (nm, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-       } else
-       {
-               addr = (guint8 *)mono_compile_method_checked (method, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-       }
+       else
+               nm = method;
+       addr = (guint8 *)mono_compile_method_checked (nm, error);
+       return_val_if_nok (error, NULL);
        return mono_get_addr_from_ftnptr (addr);
 }
 #endif