[Mono-dev] suggestion to fix remoting behavior

Andrey Chernomyrdin chernomyrdin+mono-devel-list at gmail.com
Sat Dec 17 04:20:32 EST 2011


On Thu, Dec 15, 2011 at 2:57 PM, Robert Jordan <robertj at gmx.net> wrote:

> Hi Andrey,
>
> Do you have a test case for these issues?
>
> Thanks
> Robert
>
>
Hello Robert!

Thank you for your quick reply.

After an additional research I've decided to cancel patch#1. This
issue (different behavior in .NET and Mono) takes place, but suggested
patch is incorrect.
I will try to find workaround in my application.

Below is the test case for patch#2 (patch.return-value.diff, link:
https://gist.github.com/1480249).

Issue
=====
Mono doesn't send the results of remote method execution to
IDinamicMessageSink.ProcessMessageFinish().
.NET Framework (2.0 and 4.0) sends to
IDinamicMessageSink.ProcessMessageFinish() an instance of
ReturnMessage class that implements IMethodReturnMessage interface.
This interface contains all necessary information (return vlaue,
exception, out args and modified call context).
Mono sends an istance of MethodCall class, exactly the same as to
IDinamicMessageSink.ProcessMessageStart().
It seems to be a bug in Mono sources and I have suggested the patch.


Test application
================
This test application illustrates an issue in Mono runtime.
Server and client objects are created in a single application (for the
simplification of an example).
They interoperate through Remoting using IPC channel.
Class MyDynamicMessageSink implements dynamic message sink to handle
remoting method execution.


Source code
===========
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;

namespace Patch2_Test
{
  class Program
  {
    static void Main(string[] args)
    {
      // Initialize server side remoting
      ChannelServices.RegisterChannel(new IpcChannel("ipc_test"), false);
      RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestServer),
"TestService", WellKnownObjectMode.Singleton);
      Context.RegisterDynamicProperty(new MyDynamicSinkProvider(),
null, Context.DefaultContext);

      // Get proxy to remote server
      TestServer server =
(TestServer)Activator.GetObject(typeof(TestServer),
"ipc://ipc_test/TestService");

      // Execute remote method without exception
      server.TestMethod(false);

      // Execute remote method raising exception
      try { server.TestMethod(true); }
      catch { }
    }

    // Server class
    class TestServer : MarshalByRefObject
    {
      public string TestMethod(bool throwException)
      {
        if (throwException)
          throw new Exception("TestException");
        return "Hello";
      }
    }

    // Dynamic message sink
    public class MyDynamicMessageSink : IDynamicMessageSink
    {
      public void ProcessMessageStart(IMessage reqMsg, bool bCliSide,
bool bAsync)
      { }

      public void ProcessMessageFinish(IMessage replyMsg, bool
bCliSide, bool bAsync)
      {
        // Don't handle messages on client side
        if (bCliSide) return;

        Console.WriteLine("*** Executing
IDynamicMessageSink.ProcessMessageFinish()");

        // Check replyMsg type
        Console.WriteLine("replyMsg is instance of " + (replyMsg as
object).GetType().Name);

        // Get return value and exception
        IMethodReturnMessage returnMessage = replyMsg as IMethodReturnMessage;
        if (returnMessage != null)
        {
          Console.WriteLine("ReturnValue: " +
(returnMessage.ReturnValue != null ?
returnMessage.ReturnValue.ToString() : "NULL"));
          Exception e = returnMessage.Exception;
          Console.WriteLine("Exception: " + (returnMessage.Exception
!= null ? returnMessage.Exception.Message : "NULL"));
        }
        else
          Console.WriteLine("replyMsg doesn't support IMethodReturnMessage");

        // Try to get return value from replyMsg properties
        Console.WriteLine("replyMsg.Properties[\"__Return\"]: " +
(replyMsg.Properties["__Return"] != null ?
replyMsg.Properties["__Return"].ToString() : "<none>"));
        Console.WriteLine();
      }
    }

    // Dynamic message sink provider
    public class MyDynamicSinkProvider : IDynamicProperty,
IContributeDynamicSink
    {
      IDynamicMessageSink IContributeDynamicSink.GetDynamicSink()
      { return new MyDynamicMessageSink(); }

      string IDynamicProperty.Name
      { get { return "MyDynamicSinkProvider"; } }
    }

  }
}


Program output in .NET Framework 4.0
=============================================
*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of ReturnMessage
ReturnValue: Hello
Exception: NULL
replyMsg.Properties["__Return"]: Hello

*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of ReturnMessage
ReturnValue: NULL
Exception: TestException
replyMsg.Properties["__Return"]: <none>


Program output in Mono 2.10.6
=============================================
*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of MethodCall
replyMsg doesn't support IMethodReturnMessage
replyMsg.Properties["__Return"]: <none>

*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of MethodCall
replyMsg doesn't support IMethodReturnMessage
replyMsg.Properties["__Return"]: <none>


Program output under Mono 2.10.6 with patch
==============================================
The same as in .NET Framework 4.0
                               	

-- 
Andrey Chernomyrdin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20111217/a613d5eb/attachment-0001.html 


More information about the Mono-devel-list mailing list