Bug 17325 - RealProxy returns MarshalByRefObject for an Interface instead of the real interface type
Summary: RealProxy returns MarshalByRefObject for an Interface instead of the real int...
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: Remoting (show other bugs)
Version: 3.2.x
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: Aleksey Kliger
URL:
Depends on:
Blocks:
 
Reported: 2014-01-20 07:55 UTC by Rogier
Modified: 2017-08-14 21:47 UTC (History)
7 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description Rogier 2014-01-20 07:55:15 UTC
RealProxy returns System.MarshalByRefObject for an Interface instead of the real interface type.

Possibly because in RealProxy.cs the following code is present:

	
		public Type GetProxiedType() 
		{
			if (_objTP == null) {
				if (class_to_proxy.IsInterface) return typeof(MarshalByRefObject);
				else return class_to_proxy;
			}
			return InternalGetProxyType (_objTP);
		}

For an interface the real proxied type should be returned however (using an Invoke on the proxied type).


To reproduce this try:


using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;

namespace TestRmiProxy
{
    class Program
    {
        static void Main(string[] args)
        {
            IComparable transparentProxy = (IComparable)new ProxyTest().GetTransparentProxy();
			Console.Out.WriteLine (transparentProxy.GetType ());
            Console.Out.WriteLine("transparentProxy = {0}", transparentProxy.GetType().IsAssignableFrom(typeof(IComparable)));
        }
    }

    public class ProxyTest : RealProxy
    {
        public ProxyTest() : base(typeof(IComparable))
        {
        }

        public override IMessage Invoke(IMessage msg)
        {
            // Should be called!
            return new ReturnMessage(typeof(IComparable), null, 0, null, null);
        }
    }
}


Should output (.NET):

System.IComparable
transparentProxy = True


But outputs (Mono):

System.MarshalByRefObjext
transparentProxy = False
Comment 1 Rogier 2014-01-29 10:27:51 UTC
Seems to be a runtime issue.
InternalGetTransparentProxy /
Comment 2 Rogier Hofboer 2014-02-26 16:29:52 UTC
Closely related to bug 1013
Comment 3 Rogier Hofboer 2017-03-01 10:02:51 UTC
This is still a problem in mono 4.8.x and in master (5.x.x) with reference sources, because it is caused by the runtime.
Comment 4 Rogier Hofboer 2017-08-07 07:52:13 UTC
Example on how this fails with SimpleInjector:


using SimpleInjector;
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;

namespace Bug17325
{
    public class MainClass
    {
        public static void Main(string[] args) {
            Container container = new Container();
			IComparable transparentProxy = (IComparable)new ProxyTest().GetTransparentProxy();
			container.RegisterSingleton<IComparable>(transparentProxy);
			container.Verify();

            var comparable = container.GetInstance<IComparable>();
            Console.Out.WriteLine(comparable.GetType());
			Console.Out.WriteLine("comparable = {0}", comparable.GetType().IsAssignableFrom(typeof(IComparable)));
        }
    }

	public class ProxyTest : RealProxy
	{
		public ProxyTest() : base(typeof(IComparable))
		{
		}

		public override IMessage Invoke(IMessage msg)
		{
			// Should be called!
			return new ReturnMessage(typeof(IComparable), null, 0, null, null);
		}
	}
}
Comment 5 Aleksey Kliger 2017-08-10 17:15:01 UTC
Rogier: I took a stab at fixing this (https://github.com/mono/mono/pull/5350).  If you're able to build mono, I'd appreciate it if you could try the fix in a variety of scenarios - it feels a little bit fragile but I don't have many remoting tests.  The example from Comment 4 works.

As it happens System.Object.GetType() is a little bit special in that Mono's JIT tries to replace calls to that method by a direct access to a System.Type that's stored in the vtable.  When we initialize the vtable for a transparent proxy, we just copy the System.Type from the "proxied class".  But when we're proxying an interface, the proxied class is just MonoByRefObject, so we copied the wrong type.
Comment 6 Rogier Hofboer 2017-08-11 14:41:22 UTC
Aleksey: This fix works for our use case. Thanks!

Note You need to log in before you can comment on or make changes to this bug.