Bug 319987 (MONO77191) - [PATCH] Mono remoting runtime can not resolve overload method during remote request method call processing.
Summary: [PATCH] Mono remoting runtime can not resolve overload method during remote r...
Status: RESOLVED FIXED
Alias: MONO77191
Product: Mono: Runtime
Classification: Mono
Component: remoting (show other bugs)
Version: unspecified
Hardware: Other Linux
: P3 - Medium : Normal
Target Milestone: ---
Assignee: Lluis Sanchez
QA Contact: Mono Bugs
URL:
Whiteboard:
Keywords: accessibility, interop
Depends on:
Blocks:
 
Reported: 2006-01-09 18:53 UTC by Alexey Gapotchenko
Modified: 2007-09-15 21:24 UTC (History)
3 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
VS2005 .NET solution for bug reproduction test building (3.61 KB, application/octet-stream)
2006-01-09 18:56 UTC, Thomas Wiest
Details
RemotingServices.patch (1.21 KB, patch)
2006-01-15 05:20 UTC, Thomas Wiest
Details | Diff
RemotingServices2.diff (1.57 KB, patch)
2006-01-17 11:47 UTC, Thomas Wiest
Details | Diff
More Simple TestCase (monodevelop solution) (.tar.gz) (19.98 KB, application/octet-stream)
2007-02-02 13:14 UTC, Thomas Wiest
Details
bug-77191.diff (1.34 KB, patch)
2007-02-05 15:44 UTC, Thomas Wiest
Details | Diff
bug-77191-testcase.cs (945 bytes, text/plain)
2007-02-05 15:47 UTC, Thomas Wiest
Details
bug-77191-testcase-http.cs (949 bytes, text/plain)
2007-02-05 18:59 UTC, Thomas Wiest
Details
bug-77191-SoapMessageFormatter.diff (2.22 KB, patch)
2007-02-05 21:36 UTC, Thomas Wiest
Details | Diff
bug-77191-Tests.diff - S.R.Remoting Unit Tests (2.02 KB, patch)
2007-02-05 21:37 UTC, Thomas Wiest
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wiest 2007-09-15 19:43:49 UTC


---- Reported by alex.gap@mail.ru 2006-01-09 11:53:17 MST ----

Description of Problem:
Mono remoting runtime can not resolve overload method during remote request
method call processing. Microsoft .NET implementation works with success
for this case.

Steps to reproduce the problem:
Compile this file with gmcs (don't forget /r:System.Runtime.Remoting). Then
run with mono <file.exe>:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
using System.Net.Sockets;
using System.Net;

namespace MonoRemotingBug
{
    interface I1 : IDisposable
    {
        void Test1();
    }

    interface I2
    {
        void Test2();
        void Test2(bool argument);
    }

    interface I3 : I1, I2
    {
    }

    interface I4 : I1
    {
    }

    interface I5 : I4, I3
    {
    }

    class RemotedClass : MarshalByRefObject, I5
    {
        ~RemotedClass()
        {
            Dispose(false);
        }

        public void Test1()
        {
            Console.WriteLine("Test1 OK.");
        }

        public void Test2()
        {
            Console.WriteLine("Test2.1 OK");
        }

        public void Test2(bool argument)
        {
            Console.WriteLine("Test2.2 OK");
        }

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
                Console.WriteLine("Test3 OK");
        }
    }

    class Program
    {
        static int FindFreePort()
        {
            Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
            try
            {
                socket.Bind(new IPEndPoint(IPAddress.Any, 0));
                return ((IPEndPoint)socket.LocalEndPoint).Port;
            }
            finally
            {
                socket.Close();
            }
        }

        static void Main(string[] args)
        {
            try
            {
                int port = FindFreePort();
                ChannelServices.RegisterChannel(new TcpChannel(port));
                RemotedClass remotedClass = new RemotedClass();
                RemotingServices.Marshal(remotedClass, "Root");
                Console.WriteLine("Server started.");
                try
                {
                    I5 i = (I5)RemotingServices.Connect(typeof(I5),
                        string.Format("tcp://localhost:{0}/Root", port));
                    try
                    {
                        i.Test1();
                        i.Test2();
                        i.Test2(true);
                        i.Dispose();
                    }
                    catch
                    {
                        Console.WriteLine("Some test have failed. See
pending error messages for details.");
                        throw;
                    }
                    Console.WriteLine("All OK, congradulations!");
                }
                finally
                {
                    RemotingServices.Disconnect(remotedClass);
                    Console.WriteLine("Server stopped.");
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e);
            }
        }
    }
}

Actual Results:
Server started.
Test1 OK.
Test2.1 OK
Test2.2 OK
Some test have failed. See pending error messages for details.
Server stopped.
System.Reflection.AmbiguousMatchException: Ambiguous matching in method
resolution

Server stack trace:
in <0x000a4> System.Reflection.Binder:FindMostDerivedMatch
(System.Reflection.MethodBase[] match)
in <0x0020a> System.MonoType:GetMethodImpl (System.String name,
BindingFlags bindingAttr, System.Reflection.Binder binder,
CallingConventions callConvention, System.Type[] types,
System.Reflection.ParameterModifier[] modifiers)
in <0x00023> System.Type:GetMethod (System.String name, BindingFlags
bindingAttr)
in <0x00051> System.Runtime.Remoting.RemotingServices:GetMethodBaseFromName
(System.Type type, System.String methodName, System.Type[] signature)
in <0x00058> System.Runtime.Remoting.Messaging.MethodCall:ResolveMethod ()
in <0x0007e> System.Runtime.Remoting.Messaging.MethodCall:.ctor
(System.Runtime.Remoting.Messaging.Header[] headers)
in <0x005e6>
System.Runtime.Serialization.Formatters.Binary.MessageFormatter:ReadMethodCall
(System.IO.BinaryReader reader, Boolean hasHeaders,
System.Runtime.Remoting.Messaging.HeaderHandler headerHandler,
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter)
in <0x000ba>
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter:NoCheckDeserialize
(System.IO.Stream serializationStream,
System.Runtime.Remoting.Messaging.HeaderHandler handler)
in <0x00010>
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter:Deserialize
(System.IO.Stream serializationStream,
System.Runtime.Remoting.Messaging.HeaderHandler handler)
in <0x00248>
System.Runtime.Remoting.Channels.BinaryServerFormatterSink:ProcessMessage
(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders
requestHeaders, System.IO.Stream requestStream, IMessage responseMsg,
ITransportHeaders responseHeaders, System.IO.Stream responseStream)

Exception rethrown at [0]:

in <0x006dc> System.Runtime.Remoting.Proxies.RealProxy:PrivateInvoke
(System.Runtime.Remoting.Proxies.RealProxy rp, IMessage msg,
System.Exception exc, System.Object[] out_args)


Expected Results:
Server started.
Test1 OK.
Test2.1 OK
Test2.2 OK
Test3 OK
All OK, congradulations!
Server stopped.

How often does this happen? 
Always

Additional Information:



---- Additional Comments From alex.gap@mail.ru 2006-01-09 11:56:25 MST ----

Created an attachment (id=169062)
VS2005 .NET solution for bug reproduction test building




---- Additional Comments From robertj@gmx.net 2006-01-10 14:18:42 MST ----

This is not a remoting problem. It's a binder bug.
See https://bugzilla.novell.com/show_bug.cgi?id=MONO77079.


*** This bug has been marked as a duplicate of https://bugzilla.novell.com/show_bug.cgi?id=MONO77079 ***



---- Additional Comments From robertj@gmx.net 2006-01-14 22:20:00 MST ----

It wasn't the binder. Here comes the patch.




---- Additional Comments From robertj@gmx.net 2006-01-14 22:20:31 MST ----

Created an attachment (id=169063)
RemotingServices.patch




---- Additional Comments From lluis@ximian.com 2006-01-16 13:18:54 MST ----

I don't think this patch is correct. If the message doesn't provide a
signature, it means that the method is not overloaded (so
type.GetMethod (methodName, methodBindings) should be enough), not
that it has no parameters. Maybe the client is failing to provide the
signature in an overloading case?



---- Additional Comments From alex.gap@mail.ru 2006-01-16 16:19:06 MST ----

However this patch solves visible problem.
I am agreed with Lluis about overload signature. But I also missed the
real application of such mechanism in my first report: it used in
Dispose()/Dispose(bool) pattern in my server application. I should
note that Dispose() is public, and Dispose(bool) is protected. And as
far as I know it's not possible to invoke non public methods through
remoting *by design*, so type.GetMethod (methodName, methodBindings)
should not be the source of ambigity but it does! As a consequence I
can presume that methodBindings has invalid value in this call cause
it *must* contain System.Reflection.BindingFlags.Public flag only
without System.Reflection.BindingFlags.NonPublic.

Case described in the first report is different. It can fail due to
wrong or absent overload signature provided by client.
I'll try to make test to find out possibility of wrong overload
signature provided by Mono client to MS .NET server.

And one more question. It doesn't possible to repeat same problems
with ContextBoundObject. I always thought that they use same
invokation dispatch mechanism (for example,            
RemotingServices.ExecuteMessage(...)). But in real tests such
assumption is not confirmed (for Mono test from my first report works
succesfuly in case of ContextBoundObject). Am I missed something, or
does Mono use separate dispatching mechanisms for ContextBoundObject
and channel based invokations?




---- Additional Comments From robertj@gmx.net 2006-01-17 01:43:06 MST ----

The methodBindings are indeed

static readonly BindingFlags methodBindings =
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

Hence no wonder about the ambiguity ;-)

The naive thought to remove BindingFlags.NonPublic fixes this bug,
but it also breaks the activation unit tests regarding
WellKnownServices:

1) MonoTests.Remoting.ActivationTests.TestCreateTcpWkoSingleCall :
2) MonoTests.Remoting.ActivationTests.TestCreateTcpWkoSingleton :
3) MonoTests.Remoting.ActivationTests.TestCreateHttpWkoSingleCall : 
4) MonoTests.Remoting.ActivationTests.TestCreateHttpWkoSingleton :
System.InvalidCastException : Cannot cast from source type to
destination type.
in [0x00188] (at
/usr/src/mono/head/mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs:219)
System.Runtime.Remoting.Proxies.RealProxy:PrivateInvoke
(System.Runtime.Remoting.Proxies.RealProxy rp, IMessage msg,
System.Exception exc, System.Object[] out_args)


I'm looking at this.




---- Additional Comments From robertj@gmx.net 2006-01-17 04:47:14 MST ----

Got it:

the remoting field accessors System.Object.FieldGet/Set are
private, hence GetMethodBaseFromName must use BindingFlags.NonPublic
to be able to look them up.




---- Additional Comments From robertj@gmx.net 2006-01-17 04:47:55 MST ----

Created an attachment (id=169064)
RemotingServices2.diff




---- Additional Comments From alex.gap@mail.ru 2006-01-17 17:12:08 MST ----

I created variation of the first test to check overload signature sent
by client. Server was running on MS .NET 2.0, client was running on
Mono 1.1.12.1. All tests are passed. So problem was on server side.
Lluis' suspection has not been confirmed.

Thanks for quick patch and responses.




---- Additional Comments From lluis@ximian.com 2006-01-26 09:37:35 MST ----

The patch works because of https://bugzilla.novell.com/show_bug.cgi?id=MONO77367. The problem is that a call to
GetMethod(name, Type.EmptyTypes) will only find the method if it has
no parameters. If the message does not have a signature it doesn't
mean that the target method does not have parameters, it means that
the method is not overloaded.



---- Additional Comments From robertj@gmx.net 2006-01-29 06:19:17 MST ----

Okay, but the binding flags still have to be changed to Public,
like in the second patch. Otherwise the server won't be able
to lookup methods having an overload not seen by the client
(like the protected Dispose(bool) method in Alex' sample).
And the special case Object.FieldGetter/Setter () must be
handled too. Do you agree?




---- Additional Comments From lluis@ximian.com 2006-01-31 14:10:04 MST ----

What if:
* The client uses reflection to call a private remote method.
* The client calls an interface method which is not overloaded, but
which is overloaded (and public) in the remote implementation class.

This needs further research.



---- Additional Comments From alex.gap@mail.ru 2006-02-01 11:24:15 MST ----

Q: What if the client uses reflection to call a private remote method?
A: Server throws exception with approx. description "Impossible to
invoke non-public method through remoting". .NET 1.1 did in that way -
I had experience with it.




---- Additional Comments From informatique.internet@fiducial.fr 2007-02-02 06:14:47 MST ----

Created an attachment (id=169065)
More Simple TestCase (monodevelop solution) (.tar.gz)




---- Additional Comments From informatique.internet@fiducial.fr 2007-02-02 06:16:35 MST ----

Client :

using System;

namespace MonoTestInterface.Client
{
	public interface ITestMono
	{
		string montest(); 
	}
}

Server

using System;
using MonoTestInterface.Client;

namespace MonoTestInterface
{
	public class CMonoTest:MarshalByRefObject,ITestMono
	{
		public string montest()
		{
			return "blah";
		}
		

		
		public int montest(string a)
		{
			return 1;
		}

	}
}

Test :


using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using MonoTestInterface.Client;


namespace TestClient
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			Console.WriteLine("Hello World!");
			ChannelServices.RegisterChannel(new TcpChannel());
			ITestMono test=(ITestMono )Activator.GetObject(typeof (ITestMono
),"tcp://10.69.100.164:4570/MonoTest");
			Console.WriteLine(test.montest());
		}
	}
}

Result : 
Unhandled Exception: System.Reflection.AmbiguousMatchException:
Ambiguous matching in method resolution




---- Additional Comments From informatique.internet@fiducial.fr 2007-02-02 06:17:04 MST ----

Is there some news about this bug?



---- Additional Comments From robertj@gmx.net 2007-02-05 08:44:44 MST ----

Created an attachment (id=169066)
bug-77191.diff




---- Additional Comments From robertj@gmx.net 2007-02-05 08:47:10 MST ----

Created an attachment (id=169067)
bug-77191-testcase.cs




---- Additional Comments From robertj@gmx.net 2007-02-05 08:58:55 MST ----

The new patch fixes the real issue: MethodCall.ResolveMethod
didn't respect the type returned by CastTo ().

This means that when a client is calling an interface
method, the server will lookup the method in the concrete
type, which can lead to AmbiguousMatchExceptions when 
this concrete type has overloads.




---- Additional Comments From lluis@ximian.com 2007-02-05 09:27:25 MST ----

The patch looks correct (I hope it really is :-)
Feel free to commit. 
Thanks!



---- Additional Comments From robertj@gmx.net 2007-02-05 11:58:22 MST ----

We have to fix a similar problem in HttpChannel as well:

In file

http://svn.myrealbox.com/source/trunk/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapMessageFormatter.cs

BuildMethodCallFromSoapMessage() is calling

SoapServices.DecodeXmlNamespaceForClrTypeNamespace()

to get the type of method but it doesn't use the results.
It goes ahead with the server type which is wrong. We need here
a CastTo-like method.




---- Additional Comments From robertj@gmx.net 2007-02-05 11:59:06 MST ----

Created an attachment (id=169068)
bug-77191-testcase-http.cs




---- Additional Comments From robertj@gmx.net 2007-02-05 14:36:28 MST ----

Created an attachment (id=169069)
bug-77191-SoapMessageFormatter.diff




---- Additional Comments From robertj@gmx.net 2007-02-05 14:37:18 MST ----

Created an attachment (id=169070)
bug-77191-Tests.diff  - S.R.Remoting Unit Tests




---- Additional Comments From robertj@gmx.net 2007-02-05 14:39:48 MST ----

bug-77191-SoapMessageFormatter.diff fixes the issue in HttpChannel.

bug-77191-Tests.diff adds test cases for both issues.





---- Additional Comments From robertj@gmx.net 2007-02-05 15:02:53 MST ----

If patch `bug-77191-SoapMessageFormatter.diff' doesn't apply correctly
then it needs a unix2dos conversion.




---- Additional Comments From robertj@gmx.net 2007-05-03 12:39:40 MST ----

*** https://bugzilla.novell.com/show_bug.cgi?id=MONO81519 has been marked as a duplicate of this bug. ***



---- Additional Comments From joncham@gmail.com 2007-05-04 08:18:37 MST ----

Robert, your patches fix my duplicate bug. Can you apply the approved
patch (bug-77191.diff) if the rest isn't reviewed shortly? 



---- Additional Comments From lluis@ximian.com 2007-05-07 11:24:06 MST ----

The patch looks ok to me. Please commit. Thanks!



---- Additional Comments From robertj@gmx.net 2007-05-07 11:53:25 MST ----

Fixed in SVN r76839.


Imported an attachment (id=169062)
Imported an attachment (id=169063)
Imported an attachment (id=169064)
Imported an attachment (id=169065)
Imported an attachment (id=169066)
Imported an attachment (id=169067)
Imported an attachment (id=169068)
Imported an attachment (id=169069)
Imported an attachment (id=169070)

Unknown bug field "cf_op_sys_details" encountered while moving bug
   <cf_op_sys_details>Linux g2 2.6.12.1 #12 Wed Oct 26 02:26:02 EEST 2005 i686 unknown</cf_op_sys_details>
Skipping unknown keyword: portability.