[Mono-list] Remoting + interface parameter names = a bug ?

Yuri Leikind y.leikind@sam-solutions.net
Fri, 18 Jun 2004 16:52:52 +0300


Hello all,

Looks like I have found an astonishing thing:

If I have a server that exposes some type via remoting, and 
this type implements an interface with the help of which
the type is accessed in the remoting client, the parameter names
in interface methods declarations influence runtime. 

In other words, if the parameters names are not the same,
the call to the remote object will raise an exception.

Here is the code for you to believe me:

==========     IFactorial.cs   ==========

namespace ProofOfConcepts{
    public interface IFactorial{
        //ulong CalculateFactorial(uint a);  // With this line everything  works
        ulong CalculateFactorial(uint b);    // With this line it doesn't
    }
}


==========     Server.cs   ==========
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;

namespace ProofOfConcepts{
    
    public class Calculator : MarshalByRefObject, IFactorial{
        public ulong CalculateFactorial(uint a){
            ulong res = 1;
            for (uint i=1 ; i<=a; i++)
                res = res * i;
            Console.WriteLine("!{0} = {1}", a, res);
            return res;
        }
    }
    
    class Server{
        public Server(){
            HttpChannel channel = new HttpChannel(60000);
            ChannelServices.RegisterChannel(channel);
            Type facType = Type.GetType("ProofOfConcepts.Calculator");
            RemotingConfiguration.RegisterWellKnownServiceType(
                facType,
                "MyEndPoint",
                WellKnownObjectMode.Singleton );            
        }
        
        void Listen(){
            Console.WriteLine("Press Enter to exit...");
            Console.ReadLine( );
        }
        
        public static void Main(){
            new Server().Listen();
        }
    }

}

==========     Client.cs   ==========

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;


namespace ProofOfConcepts{
    class Client{
        public static void Main(){
            HttpChannel channel = new HttpChannel(0);
            ChannelServices.RegisterChannel(channel);
            MarshalByRefObject obj = 
                (MarshalByRefObject) RemotingServices.Connect(
                    typeof(ProofOfConcepts.IFactorial),
                    "http://localhost:60000/MyEndPoint");
            IFactorial cal = (IFactorial) obj;
            Console.WriteLine("!4 = {0}", cal.CalculateFactorial(4));
        }
    }
}

==============================

To compile these, issue the following commands:

mcs   /t:library /out:IFactorial.dll IFactorial.cs

mcs  /r:IFactorial.dll,System.Runtime.Remoting.dll  /out:Server.exe Server.cs

mcs  /r:IFactorial.dll,System.Runtime.Remoting.dll  /out:Client.exe Client.cs


Now run the server, then start the client.

I get the following in the Client.exe console::

===============================

leikind@pc324:~/cs/appDomains/my_remoting$ mono Client.exe 

Unhandled Exception: System.IndexOutOfRangeException: Array index is out of range.

Server stack trace: 
in <0x005ea> System.Runtime.Remoting.Channels.SoapMessageFormatter:BuildMethodCallFromSoapMessage (System.Runtime.Serialization.Formatters.SoapMessage,string)
in <0x001f5> System.Runtime.Remoting.Channels.SoapServerFormatterSink:ProcessMessage (System.Runtime.Remoting.Channels.IServerChannelSinkStack,System.Runtime.Remoting.Messaging.IMessage,System.Runtime.Remoting.Channels.ITransportHeaders,System.IO.Stream,System.Runtime.Remoting.Messaging.IMessage&,System.Runtime.Remoting.Channels.ITransportHeaders&,System.IO.Stream&)


Exception rethrown at [0]: 

in <0x00748> System.Runtime.Remoting.Proxies.RealProxy:PrivateInvoke (System.Runtime.Remoting.Proxies.RealProxy,System.Runtime.Remoting.Messaging.IMessage,System.Exception&,object[]&)

===============================

If you cache in the interface  line 
	ulong CalculateFactorial(uint b);  
to
	ulong CalculateFactorial(uint a);  
recompile all the three assemblies, and run again, everything will work just fine.

I run Mono 0.95

On MS .NET it works fine in all cases

Does anyone have any comments?

-- 
Best regards,
Yuri Leikind