Properly Closing and Unloading the RDotNet Engine.

Jan 24, 2012 at 11:19 PM

I'm Opening the REngine like this

			console = new RDotNet.Devices.ConsoleDevice();
			REngine.SetDllDirectory(@"C:\Program Files\R\R-2.12.1\bin\i386");
			engine = REngine.CreateInstance("RDotNet",console);

 

then doing a bunch of R commands that works successfully.

 

Finally I close the engine like this:

			engine.Close();
			engine.Dispose();

If I repeat the same procedure again, I get a crash from the same R commands that previously worked (In this case the engine can't find the "ts()" function).

I'm lead to believe that this is problem with loading, unloading and reloading the REngine. Any tips?

 

Thanks

Jan 26, 2012 at 5:41 PM

I'm seeing exactly the same issue here.

 

Getting an SEHException when running working code for the second time.  I've looked in the Dispose method and this line:

Proxy.Rf_endEmbeddedR(0);

In the REngine.cs class is never hit:

        protected override void Dispose(bool disposing)
        {
            if (instances.ContainsKey(ID))
            {
                instances.Remove(ID);
            }

            if (IsRunning)
            {
                if (disposing)
                {
                    Proxy.Rf_endEmbeddedR(0);
                }
                proxy = null;
                if (adapter != null)
                {
                    adapter.Dispose();
                    adapter = null;
                }
            }

            base.Dispose(disposing);
        }

I'm currently assigned to get this working asap for a current project.  If you make any progress let me know and I'll do the same.

Seems this has been a problem for a number of people for a while now.


Regards,

Jan 27, 2012 at 10:09 AM

One thing I have noticed is if you are seeing these crashes during testing you may actually be worrying about false positives.

For instance if you are running NUnit and Test Driven dot net you need to end the ProcessInvocation86.exe process between test runs.  Hopefully more to follow!

Feb 27, 2012 at 6:45 AM
Edited Feb 27, 2012 at 8:20 AM

I am also having still problem, and this is critical for me: I have to manage creation and destruction of instances of class RDotNet many times because my code runs as a plugin and is launched by mainapp each time in different appdomain. 

My env: Vista, x86, R-Community-5.0 (R 2.13.2), .NET 3.5/4.0

My code in windows forms simple app is like this:

 

private void button7_Click(object sender, EventArgs e)        
{

          string sRHome = FindRPath();           

          System.Environment.SetEnvironmentVariable("PATH",
System.Environment.GetEnvironmentVariable("PATH") + ";" + sRHome);
          REngine.SetDllDirectory(sRHome);

          using (REngine engine = REngine.CreateInstance("RDotNet"))            
          {               

              NumericVector random = 
engine.EagerEvaluate("rnorm(5, 0, 1)").AsNumeric(); } }

 

Works fine first time. Second time it hangs on the line with EagerEvaluate() call consuming CPU 100%. I have tried to check if bug persists: tested with R.NET 1.3 for .NET 3.5 and built latest source R.NET 1.4.1 for .NET 4.0. The problem persists. 
I would like to ask author kos59125 to advise on this. Is there a way to fix this problem? Anyone has found some workarounds? Thank you.

Apr 14, 2012 at 12:19 PM

Tested new version of R.NET as of 14.04.2012. The bug persists. I create and init new instance of R.NET. Make calculations. Close and destroy it. Open new instance - system hangs with 100% CPU on .Initialize() method.

Apr 27, 2012 at 9:21 AM

I have the same issue. Anyone can help? Thanks

May 2, 2012 at 1:01 PM
Edited May 2, 2012 at 1:26 PM

Okay with some testing I got the REngine properly "destroyed" with:

 

If Not IsNothing(engine) then
engine.SetHandleAsInvalid
engine.close
else
REngine.SetDllDirectory(dlldirectory)
engine = REngine.CreateInstance("RDotNet", {"-q"}
End If

 

It might be far away from any substantial proof but it is working somehow!

Hope to be able to help you guys!

Jun 21, 2012 at 6:07 PM

Hello ops,

There are other threads on this issue and all of them conclude that R.NET can only be initialized (and closed) once per process.

What I have done is create a separate EXE that I call RHost. I use Microsoft's WCF (Windows Communication Foundation) to establish inter-process communications between RHost and my application. The application launches the RHost, connects to it then issues commands and gets results back. It took some trial and error but it works.

So the application just launches the RHost as needed and then just leaves it running. If I need to close R, I call the shutdown method on the RHost and wait for the RHost process to exist. (I used a timer to establish a time out so if RHost does not exit after 30 seconds or so, I just kill the process).

Here is my WCF service contract interface in VB (note R_Result and R_ExceptionInfo are my own classes as well)

<ServiceContract(Namespace:="net.pipe://localhost/R")> Public Interface IR_Host

Delegate Sub ShutdownNotify()

<OperationContract()> <FaultContract(GetType(String))> _

Function StartUp() As Boolean

<OperationContract()> <FaultContract(GetType(String))> _

Sub Shutdown()

<OperationContract(), FaultContract(GetType(String))> _

Function Execute(cmd As String) As R_Result

<OperationContract(), FaultContract(GetType(String))> _

Function ExecuteString(cmd As String) As String

<OperationContract(), FaultContract(GetType(String))> _

Function ExecuteInteger(cmd As String) As Int32

<OperationContract(), FaultContract(GetType(String))> _

Function ExecuteFloat(cmd As String) As Double

<OperationContract(), FaultContract(GetType(String))> _

Function ExecuteBoolean(cmd As String) As Boolean

<OperationContract(), FaultContract(GetType(String))> _

Function GetValue(name As String) As R_Result

<OperationContract(), FaultContract(GetType(String))> _

Sub SetValue(name As String, expression As String)

<OperationContract(), FaultContract(GetType(String))> _

Function GetLastException() As R_ExceptionInfo

Sub registerCallback(ByVal func As ShutdownNotify)

End Interface

From: ops [email removed]
Sent: Sunday, February 26, 2012 10:46 PM
To: MCALLISTER,ROB (A-Spokane,ex1)
Subject: Re: Properly Closing and Unloading the RDotNet Engine. [rdotnet:287285]

From: ops

I am also having still problem, and this is critical for me: I have to manage create and destroy instances of class RDotNet many times.

My env: Vista, x86, R-Community-5.0 (R 2.13.2), .NET 3.5/4.0

My code in windows forms simple app is like this:

private void button7_Click(object sender, EventArgs e)
{

string sRHome = FindRPath();
System.Environment.SetEnvironmentVariable("PATH", System.Environment.GetEnvironmentVariable("PATH") + ";" + sRHome); REngine.SetDllDirectory(sRHome);

using (REngine engine = REngine.CreateInstance("RDotNet"))
{

NumericVector random = engine.EagerEvaluate("rnorm(5, 0, 1)").AsNumeric();

}

}

Works fine first time. Second time it hangs on the line with EagerEvaluate() call consuming CPU 100%. I have tried to check if bug persists: tested with R.NET 1.3 for .NET 3.5 and built latest source R.NET 1.4.1 for .NET 4.0. The problem persists.
I would like to ask author kos59125 to advise on this. Is there a way to fix this problem? Anyone has found some workarounds? Thank you.

Jun 22, 2012 at 10:39 AM

Don't create the instance in the event handler, create it in the Form's constructor say and make it a available to the rest of the form. I know the using directive should release the object for garbage collection but this is indeterminate. You need to make sure there is only ever ONE instance of REngine 

Jul 11, 2012 at 6:18 AM

I have the problem too.hope author kos59125 can fix this problem.now i use a static variable.

Aug 15, 2012 at 5:26 PM
kulong995 wrote:

I have the problem too.hope author kos59125 can fix this problem.now i use a static variable.

I have solved this issue by:

engine = REngine.GetInstanceFromID ("RDotNet");
if (engine == null) {
  engine = REngine.CreateInstance("RDotNet", new[] {"-q"});
}

// ... your code here..

Jan 30, 2014 at 5:04 PM
Edited Jan 30, 2014 at 5:04 PM
Just make sure to not call Initialize() more than once:
engine_ = REngine.GetInstanceFromID("RDotNet");

if (engine_ == null)
{
    engine_ = REngine.CreateInstance("RDotNet");
    engine_.Initialize();
}