Bug 31091 - RemotingException thrown when invoking remote object via NUnit context
Summary: RemotingException thrown when invoking remote object via NUnit context
Alias: None
Product: Class Libraries
Classification: Mono
Component: mscorlib ()
Version: 4.0.0
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Alexander Köplinger [MSFT]
Depends on:
Reported: 2015-06-13 18:56 UTC by Hendrik
Modified: 2016-11-25 16:24 UTC (History)
3 users (show)

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

Sample Solution (201.71 KB, application/octet-stream)
2015-06-13 18:58 UTC, Hendrik
Traceback from nunit 2.4.8 crash (16.59 KB, text/plain)
2015-12-09 15:22 UTC, Neale Ferguson

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Hendrik 2015-06-13 18:56:44 UTC
I discovered a strange problem while playing with .Net Remoting and Mono.
When I invoke a remote object in code executed by NUnit this exception is thrown: 

>System.Runtime.Remoting.RemotingException : Cannot create channel sink to connect to URL 9cd3eef9_6e1f_4e0e_a4fe_0d43b3b0d157/2d2f9b_6.rem. An appropriate channel has probably not been registered. 
>Stack trace:  
>at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (System.Runtime.Remoting.Proxies.RealProxy rp, IMessage msg, System.Exception& exc, System.Object[]& out_args) [0x001e9] in /tmp/buildd/mono-4.0.1/mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs:249

When executing the exact same code from a Console application everything works fine.
Given this interface:
>public interface IEchoService {
>    string Echo(string message);

And a server hosting a implementation like this:
>var serverProvider = new BinaryServerFormatterSinkProvider();
>serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
>var channel = new TcpServerChannel("RemotingTest", 4242, serverProvider);
>ChannelServices.RegisterChannel(channel, false);
>RemotingConfiguration.RegisterWellKnownServiceType(typeof(HelloEchoService), "RemotingTest.rem", WellKnownObjectMode.Singleton);

This will cause the exception:
>public void SendEchoRequest()
>    var chan = new TcpClientChannel();
>    ChannelServices.RegisterChannel(chan, false);
>    string url = "tcp://localhost:4242/RemotingTest.rem";
>    var runner = (IEchoService)Activator.GetObject(typeof(IEchoService), url);
>    string echoMessage = runner.Echo("World");
>    Console.WriteLine(echoMessage);
>    Assert.That(echoMessage, Is.EqualTo("Hello World"));

But when running it like this from Console Main it works:
>new Program().SendEchoRequest();

The main difference between NUnit and Console that I can tell is the AppDomain.
While in NUnit the code is executed in it is own child AppDomain the Console executes it in the DefaultAppDomain.
However I haven't found anything difference while comparing this two AppDomains. 
The error also occurs when running NUnit on a Windows machine but it DOES NOT when hosting the server on Windows.
In this case both Linux and Windows NUnit runners can successfully execute the test.

After some debugging of the Mono BCL I found that the switch happens in System.Runtime.Serialization.Formatters.Binary/MessageFormatter.cs.
At line 282 MethodFlags are read (https://searchcode.com/codesearch/view/51494239/).
When running in NUnit they are IncludesLogicalCallContext|PrimitiveArguments but when in Console ExcludeLogicalCallContext|PrimitiveArguments. 
Because of this the if-statement at line 310 is entered where objectReader.ReadObjectGraph is executed which ultimately leads to the exception in System.Runtime.Remoting/RemotingServices.cs line 695 (https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs#L695)

I attached a sample solution for which reproduces the problem.
Just run the server via mono RemotingTest.Server.exe and then run the client test with MonoDevelop. 
My testing environment is Ubuntu 15.04 x64 with Mono 4.0.1 from the official Mono repository.
Comment 1 Hendrik 2015-06-13 18:58:25 UTC
Created attachment 11598 [details]
Sample Solution
Comment 2 Hendrik 2015-08-11 08:46:18 UTC
Update on this:
When running "nunit-console.exe" with "--domain=none" to code works as expected so this must be definitive an AppDomain problem.
However, when creating my own AppDomain and running the same code I cannot reproduce this issue.
Comment 3 Neale Ferguson 2015-12-01 16:23:23 UTC
Experiencing a similar situation:

1. Application Version: Mono 4.3
2. redhat 6.5
3. intel x86
4. Priority: 20 
5. Description: Nunit 2.6.4 causes remoting issues	

Details of our issue:
I have been testing nunit 2.6.4 and found that it would generate a lot remoting issues. They mentioned in their comments about some linux/mono issues they are trying to work around also.

I found if nunit runner tried to create a separate app domain/thread, mono would generate some remoting errors. For example, executing something like this:

mono --debug nunit-console.exe -domain=Single -trace=Verbose -nothread Test.dll -run=test

note, the test.dll can be any type of .net assembly since this just initiated the whole remoting wireup/teardown which is where it will generate the following error:

Unhandled Exception:
System.Runtime.Remoting.RemotingException: Cannot create channel sink to connect to URL 0af5dbf7_c938_441b_9b68_995e79617202/415bb96b_7.rem. An appropriate channel has probably not been registered.

Server stack trace:
at System.Runtime.Remoting.RemotingServices.GetClientChannelSinkChain (System.String url, System.Object channelData, System.String& objectUri) [0x0003b] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:704
at System.Runtime.Remoting.RemotingServices.GetOrCreateClientIdentity (System.Runtime.Remoting.ObjRef objRef, System.Type proxyType, System.Object& clientProxy) [0x0001d] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:646
at System.Runtime.Remoting.RemotingServices.GetRemoteObject (System.Runtime.Remoting.ObjRef objRef, System.Type proxyType) [0x00000] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:757
at System.Runtime.Remoting.RemotingServices.GetProxyForRemoteObject (System.Runtime.Remoting.ObjRef objref, System.Type classToProxy) [0x0001e] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:751
at System.Runtime.Remoting.RemotingServices.Unmarshal (System.Runtime.Remoting.ObjRef objectRef, Boolean fRefine) [0x00090] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:286
at System.Runtime.Remoting.RemotingServices.Unmarshal (System.Runtime.Remoting.ObjRef objectRef) [0x00000] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:260
at System.Runtime.Remoting.ObjRef.GetRealObject (StreamingContext context) [0x00012] in /home/mono4/mono4/mono4/mono/mcs/class/corlib/System.Runtime.Remoting/ObjRef.cs:243
at System.Runtime.Serialization.ObjectManager.ResolveObjectReference (System.Runtime.Serialization.ObjectHolder holder) [0x00009] in /home/mono4/mono4/mono4/mono/external/referencesource/mscorlib/system/runtime/serialization/objectmanager.cs:299
at System.Runtime.Serialization.ObjectManager.DoFixups () [0x00089] in /home/mono4/mono4/mono4/mono/external/referencesource/mscorlib/system/runtime/serialization/objectmanager.cs:925
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize (System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Runtime.Serialization.Formatters.Binary.__BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) [0x0007d] in /home/mono4/mono4/mono4/mono/external/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryobjectreader.cs:179
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) [0x000a4] in /home/mono4/mono4/mono4/mono/external/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs:197
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage) [0x00000] in /home/mono4/mono4/mono4/mono/external/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs:173
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.DeserializeMethodResponse (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, IMethodCallMessage methodCallMessage) [0x00000] in /home/mono4/mono4/mono4/mono/external/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs:155
at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage (IMessage msg) [0x0007e] in /home/mono4/mono4/mono4/mono/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/BinaryClientFormatterSink.cs:162

Exception rethrown at [0]:

at (wrapper managed-to-native) System.Object:__icall_wrapper_mono_remoting_wrapper (intptr,intptr)
at (wrapper remoting-invoke) NUnit.Core.ProxyTestRunner:Run (NUnit.Core.EventListener,NUnit.Core.ITestFilter,bool,NUnit.Core.LoggingThreshold)
at NUnit.Core.ProxyTestRunner.Run (EventListener listener, ITestFilter filter, Boolean tracing, LoggingThreshold logLevel) <0x41907040 + 0x00076> in <filename unknown>:0
at NUnit.ConsoleRunner.ConsoleUi.Execute (NUnit.ConsoleRunner.ConsoleOptions options) <0x418eff60 + 0x00790> in <filename unknown>:0

It seems to work with mono 3.2.1 but mono 4.3 seems to generate this.
Comment 4 Neale Ferguson 2015-12-09 15:21:03 UTC
I found with 2.4.8 I would get the error (attached). When I debugged it , I found it was when the nunit runner was doing the AppDomain.Unload() that it generated this error. The strange or not so strange thing is if I did  GC.Collect just before the app domain unload I didn’t get the error. It just seems that with all these errors it almost seems like the garbage collector is kicking in at a time that the app domain is tearing things down and the combination is causing some issues. With the 2.6.4 remoting issue its like the remoting objects were ripped away before it was done with them. Not sure is there is any correlation though.
Comment 5 Neale Ferguson 2015-12-09 15:22:09 UTC
Created attachment 14203 [details]
Traceback from nunit 2.4.8 crash
Comment 6 Neale Ferguson 2015-12-15 17:12:39 UTC
Further debugging of the problem reveals that in 3.2.1, for example, the RemotingServices:.cctor is being invoked which in turn invokes RegisterInternalChannels (). This creates a channel used by NUnit that is able to handle the URI that is being passed. For 4.3.1 the static constructor is not being invoked and the CrossDomainApp channel is not created and thus we fail.

I assume this difference is due to the introduction of the AppDomain reference code in place of the Mono version.
Comment 7 Neale Ferguson 2015-12-15 18:34:44 UTC
I take that back. I don't believe we're using the referencesource for AppDomain yet. However, the fact remains the static constructor is not being invoked in the 4.3 case. In 3.2.1 the call sequence is:

System.Runtime.Remoting.RemotingServices..cctor() in /home/mono-3.2.1/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:line 85                              
   at System.AppDomain.GetMarshalledDomainObjRef() in /home/mono-3.2.1/mcs/class/corlib/System/AppDomain.cs:line 1359                                                         
   at System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod , System.Object , System.Object[] , System.Exception ByRef )                                   
   at System.AppDomain.InvokeInDomain(System.AppDomain domain, System.Reflection.MethodInfo method, System.Object obj, System.Object[] args)
   at System.Runtime.Remoting.RemotingServices.GetDomainProxy(System.AppDomain domain)                                                                                       
   at System.AppDomain.CreateDomain(System.String friendlyName, System.Security.Policy.Evidence securityInfo, System.AppDomainSetup info)                              
   at NUnit.Util.DomainManager.CreateDomain(NUnit.Core.TestPackage package)                                               
   at NUnit.Util.TestDomain.Load(NUnit.Core.TestPackage package)                                                                                                              
   at NUnit.Util.AggregatingTestRunner.Load(NUnit.Core.TestPackage package)                                                                                                   
   at NUnit.ConsoleRunner.ConsoleUi.Execute(NUnit.ConsoleRunner.ConsoleOptions options)                                                                                        
   at NUnit.ConsoleRunner.Runner.Main(System.String[] args)                                                                                                                   
   at Drms.Tools.MpiNUnitWrapper.Wrapper.Main(System.String[] args)   

I'll investigate why things are different.
Comment 8 Neale Ferguson 2015-12-15 21:44:54 UTC
The 3.2.1 trace shows NUnit invoking NUnit.Util.DomainManager.CreateDomain but 4.3 trace does not.  That method calls System.AppDomain.CreateDomain which results in the RemotingServices() static constructor being invoked and the channel being established.
Comment 9 Neale Ferguson 2015-12-16 22:36:26 UTC
The key difference appears to be this:

3.2.1 -

[0x7f16cf3ae780: 0.08864 1] LEAVE: NUnit.Util.DefaultTestRunnerFactory:GetTargetProcessModel (NUnit.Core.TestPackage)result=0 

4.3.1 - 

[0x7fd985409760: 0.11329 1] LEAVE: NUnit.Util.DefaultTestRunnerFactory:GetTargetProcessModel (NUnit.Core.TestPackage)resu

This causes NUnit to behave differently. By forcing it to return 0 the problem disappears and everything works as expected.

The information it is using that results in the 0 or 2 result is:

Current Framework: Mono                                                                                                                            
Target Framework: Mono                                                                                                                            
Current CLR:                                                                                                                              
Target CLR: 4.0.30319                                                                                                                              
Current Framework version: 4.6                                                                                                                    
Target Framework version: 4.0

So it appears to be an issue with NUnit and not mono (other than the mono-specific code in NUnitEngine/nunit.engine/RuntimeFramework.cs).
Comment 10 Neale Ferguson 2015-12-18 17:35:37 UTC
Taking the code for DefaultTestRunnerFactgory.GetTargetProcessModel from Nunit 3.0 and putting it into Nunit 2.6.4 fixed the problem.
Comment 11 Rodrigo Kumpera 2016-01-04 20:00:23 UTC
Hey Alexander,

Could you apply the suggested fix by Neale to the nunit we ship?
Comment 12 Hendrik 2016-01-29 23:10:31 UTC
This issue is fixed with NUnit 3.0.1.
However the suggested fix by Neale does not worked for me in 2.6.4.
Comment 13 Alexander Köplinger [MSFT] 2016-11-25 16:24:05 UTC
We decided to deprecate the ancient NUnit 2.4 we ship in Mono and just keep it for compatibility and since this works in a newer NUnit, I'm closing this bug. Thanks!