Bugzilla – Bug 319987
[PATCH] Mono remoting runtime can not resolve overload method during remote request method call processing.
Last modified: 2007-09-15 21:24:46 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.