This project is read-only.

Error in deployed asp.net application

Oct 21, 2013 at 11:14 AM
Hello everyone,
I am trying to build a web application that uses r.net and works perfectly when running under the visual studio development server.
But, when I run the deploy under iis the application doesn't work and I get the following error:
[ParseException: Errore dell'applicazione.]
   RDotNet.REngine.Parse(String statement, StringBuilder incompleteStatement) +409
   RDotNet.<Defer>c__Iterator4.MoveNext() +307
   System.Linq.Enumerable.LastOrDefault(IEnumerable`1 source) +186
   RDotNet.REngine.Evaluate(String statement) +60
on the execution of this statement:
GenericVector testResult = Engine.Evaluate("t.test(group1, group2)").AsList();
From what can be?

Thank you in advance.

stefano
Oct 21, 2013 at 10:36 PM
Could you share a minimal set of code files/projects via something like github or another code hosting service; or if there is a way to zip it up and put it for download on a FTP site or other sharing facility?

I know very little of ASP+IIS, so this would help to set up a reproducible test.
Oct 22, 2013 at 9:45 AM
Here the code of my test web application, the page:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Rweb.Default" %>

<%@ Import Namespace="Rweb" %>

<!DOCTYPE html>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        Label2.Text = Rmodule.BinPath;
        Label1.Text = Environment.GetEnvironmentVariable("PATH");
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        TextBox1.Text = Rmodule.GetStringTest();
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <fieldset>
            <legend>Env. path</legend>
            <asp:Label ID="Label1" runat="server"></asp:Label>
        </fieldset>
        <fieldset>
            <legend>R bin</legend>
            <asp:Label ID="Label2" runat="server"></asp:Label>
        </fieldset>
        <br />
        <fieldset>
            <legend>Test</legend>
            <asp:Button ID="Button1" runat="server" Text="Go" OnClick="Button1_Click" />
            <asp:TextBox ID="TextBox1" runat="server" Rows="10" TextMode="MultiLine" Width="500px"></asp:TextBox>
        </fieldset>
    </form>
</body>
</html>
the class for R.net:
using RDotNet;
using System;
using System.IO;
using System.Linq;

namespace Rweb
{
    public class Rmodule
    {
        private static object syncRoot = new Object();
        private static REngine engine;

        public static string BinPath
        {
            get;
            private set;
        }

        public static REngine Engine 
        {
            get 
            { 
                if (engine == null)
                {
                    lock (syncRoot)
                    {
                        if (engine == null)
                        {
                            engine = REngine.CreateInstance("RDotNet");
                            engine.Initialize();
                        }
                    }
                }
                return engine;
            }
        }

        static Rmodule()
        {
            SetRPathEnvVariable();
        }

        private static void SetRPathEnvVariable()
        {
            BinPath = GetWinRegistryPath();
            var envPath = Environment.GetEnvironmentVariable("PATH");
            Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + BinPath);
        }

        private static string GetWinRegistryPath()
        {
            Microsoft.Win32.RegistryKey rCore = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\R-core");
            if (rCore == null)
            {
                throw new System.ApplicationException("Registry key is not found.");
            }
            bool is64Bit = System.Environment.Is64BitProcess;
            Microsoft.Win32.RegistryKey r = rCore.OpenSubKey(is64Bit ? "R64" : "R");
            if (r == null)
            {
                throw new System.ApplicationException("Registry key is not found.");
            }
            System.Version currentVersion = new System.Version((string)r.GetValue("Current Version"));
            string installPath = (string)r.GetValue("InstallPath");
            string bin = System.IO.Path.Combine(installPath, "bin");
            return currentVersion < new System.Version(2, 12) ? bin : System.IO.Path.Combine(bin, is64Bit ? "x64" : "i386");
        }

        public static string GetStringTest()
        {
            NumericVector group1 = Engine.CreateNumericVector(new double[] { 30.02, 29.99, 30.11, 29.97, 30.01, 29.99 });
            Engine.SetSymbol("group1", group1);

            //Direct parsing from R script.
            NumericVector group2 = engine.Evaluate("group2 <- c(29.89, 29.93, 29.72, 29.98, 30.02, 29.98)").AsNumeric();

            // Test difference of mean and get the P-value.

            GenericVector testResult = Engine.Evaluate("t.test(group1, group2)").AsList();
            double p = testResult["p.value"].AsNumeric().First();

            string r = String.Format("Group1: [{0}] {1}", string.Join(", ", group1), Environment.NewLine)
            + String.Format("Group2: [{0}] {1}", string.Join(", ", group2), Environment.NewLine)
            + String.Format("P-value = {0:0.000} {1}", p, Environment.NewLine);

            return r;
        }
    }
}
Remember to reference the R.net ddls and set visual studio development as server in the project properties.

The application works in this way, but no longer works if you run the deploy under iis.
Is there a security problem related to folder permissions?
Thank.
stefano
Oct 24, 2013 at 1:21 PM
Thanks for this.

Unfortunately given my lack of experience with ASP.NET, and more so given work commitments, I am unlikely to be able to replicate it myself in the near future.

Any good soul out there?
Nov 7, 2013 at 2:35 AM
Edited Nov 7, 2013 at 4:50 AM
Was able to replicate it in my test environment at first. Then I tied some other things that were working about 3 out of 4 page refreshes. Then I tried your code again and everything seems to be working consistently.

Anyways, hope that helps.

Edit: On a side note I'm doing my initialization a bit differently, is there a good reason I cant do it like this? Until I tried to run stefano's code it seem to work fine, but maybe I need the lock in there? I'm just using RNET.engine wherever I need it and theoretically it should only get created once when the application first loads right? So no need to check if engine == null?

public static class RNET
{   
    public static REngine engine = makemyengine();
    
    private static REngine makemyengine()
        {
            SetupPath();
            REngine myREngine = REngine.CreateInstance("RDotNet");
            myREngine.Initialize();
            return myREngine;
        }

        public static void SetupPath()
        {
        #.. copied from documentation page
    }
}
Nov 7, 2013 at 9:03 AM
Hello nbk,
in my example code I wanted to implement the singleton pattern but also goes well your code. the important thing is to make sure you have only one instance of the engine.

For reasons of time and work I no longer suspect the problem of web application deployment under iis. Your web application will work even after it has been deployed? Can you give me some guidance on this?
Nov 7, 2013 at 3:07 PM
Sorry I take that back, I'm having the same issue after setting visual studio to use IIS express instead of the development server.
Nov 7, 2013 at 5:07 PM
Edited Nov 7, 2013 at 5:08 PM
We were getting the same error in the F# type provider for R. This generally happens (but not always) when accessing R.NET from multiple threads. One solution is to only access R engine from a single dedicated thread. Another one which is what we ended up doing in the R type provider (and it seems to work fine) is to disable C stack checking (which might cause other issues, but it lets you use R engine from multiple threads).

See https://github.com/BlueMountainCapital/FSharpRProvider/blob/7d0ca1d204a2fb80821e9b974e9fe305ee6b43a3/src/RProvider/RInit.fs

The key piece of code that disables C stack checking is:
let varAddress = engine.DangerousGetHandle("R_CStackLimit")
System.Runtime.InteropServices.Marshal.WriteInt32(varAddress, -1)
Nov 7, 2013 at 5:13 PM
Yeah, this is an annoying issue. R recommends running threads with a 10 MB stack, and I think the defaults are around ~1 MB by default in .NET code.
Nov 7, 2013 at 10:20 PM
In the case of R provider, the stack size does not really matter - the R provider only makes very simple calls. The problem is that if R_CStackLimit is set to some value (the default), then the R engine crashes when accessed from another thread (regardless of whether it needs any stack space or not). Setting the R_CStackLimit variable disables some checking (which is probably a bad thing to do) and as a consequence, the engine can then be called from multiple threads.

There is no apparent relation between R_CStackLimit and multi-threading. It is a pure magic vaguely documented in the section 8.1.5 of the documentation.

Note that this still does not let you call REngine concurrently. If two threads make request at the same time, it will fail with access violation exception (but I suppose wrapping everything in a lock would work).
Nov 7, 2013 at 10:33 PM
tomasp wrote:
There is no apparent relation between R_CStackLimit and multi-threading. It is a pure magic vaguely documented in the section 8.1.5 of the documentation.
The documentation on embedding R is awesomely thorough isn't it? I only got the error message about the stack size being too small when running multiple threads on Linux, good to know it occurs on windows to. (I put this issue here: https://rdotnet.codeplex.com/workitem/71). My guess would be that they save the initial stack pointer address from the main thread and use that for subsequent comparisons, but don't really know. Regardless, good to know that changing the stack size for the thread pool won't matter at all.
Nov 8, 2013 at 6:28 AM
I spent a couple of hours setting up an ASP.NET project to try to repro the issues reported in this thread and elsewhere.
It is at https://github.com/jmp75/rdotnet-onboarding/tree/rdotnet-dev/WebApplicationRdn, with the caveat that I don't normally do any ASP.NET. I seem however to to have a bare bone REPL going. I get a ParseException on the line calling the lm() function, running in debug mode from VS2012,, via Chrome as a browser.
ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14)
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69)
group <- gl(2, 10, 20, labels = c("Ctl","Trt"))
weight <- c(ctl, trt)
lm.D9 <- lm(weight ~ group)
Code is at https://github.com/jmp75/rdotnet-onboarding/tree/rdotnet-dev/WebApplicationRdn; it is runing against a dev branch of R.NET, not 1.5.5. You are very welcome to fork/comment: I am not most qualified for this ASP.NET related issue.

BTW if someone knowledgeable can provide a unit test for something like this, this would be useful.

I tried to set the CStackLimit to -1; does not seem to make a difference. Would you (evolvedmicrobe and topmasp) have expected this to fix the issue?
Nov 8, 2013 at 11:03 AM
Edited Nov 8, 2013 at 12:38 PM
So far so good running my site on UltiDev UWS instead of IIS. (which I think should be fine for my purposes) Maybe how the process runs under IIS vs. UWS/Cassini is causing issues?

Edit: Make sure to set up your website as a private host instead of the default shared host when you create it n UltiDev or it will (at least with my code) crash after a few refreshes.
Nov 8, 2013 at 1:32 PM
Guys today I spent a bit of time and I think I've figured out my problem.
I realized that the web application is unable to dynamically set the environment variable PATH when runs under iis by using the following statement:
BinPath = GetWinRegistryPath();
var envPath = Environment.GetEnvironmentVariable("PATH");
// this statement not work under iis
Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + BinPath);
To test this I added manually (from Control Panel/System) the r executable folder to the environment variable and now works fine.
Setting the environment variable works perfectly when you use visual studio development server (cassini) during application development.

I take this opportunity to ask please if there is anyone who knows how to dynamically set the system variable correctly.

Thank you all.

stefano
Nov 12, 2013 at 12:32 AM
Edited Nov 12, 2013 at 1:02 AM
What exactly are you setting to what? Was not able to replicate this.

And are you able to run functions from installed packages not part of the standard libraries?
Oct 1, 2014 at 8:27 PM
Edited Oct 1, 2014 at 8:27 PM
stefano22 wrote:
Guys today I spent a bit of time and I think I've figured out my problem.
I realized that the web application is unable to dynamically set the environment variable PATH when runs under iis by using the following statement:
BinPath = GetWinRegistryPath();
var envPath = Environment.GetEnvironmentVariable("PATH");
// this statement not work under iis
Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + BinPath);
To test this I added manually (from Control Panel/System) the r executable folder to the environment variable and now works fine.
Setting the environment variable works perfectly when you use visual studio development server (cassini) during application development.

I take this opportunity to ask please if there is anyone who knows how to dynamically set the system variable correctly.

Thank you all.

stefano
Stefano,
I am currently fighting this same issue. Could you please elaborate on what exactly you did to resolve the issue?

I went into Environment Variables and added 2 entries:
  1. RHOME = C:\Program Files\R\R-3.1.1
  2. RPATH = "C:\Program Files\R\R-3.1.1\bin\i386
But this didn't seem to make any difference when testing locally on IISExpress (in Visual Studio 2013).

Any information that you can provide would be greatly appreciated.

Thanks,

sehunley
Oct 2, 2014 at 5:03 AM
Edited Oct 2, 2014 at 5:05 AM
Add "C:\Program Files\R\R-3.1.1\bin\i386" to the SYSTEM path. Restart IIS or IIS express so that the path changes can be seen by the process. That will fix your issue under IIS.


FWIW, there is a R_HOME but no RHOME or RPATH. Neither one fixes the issue mention in this bug, or others. You need to add the bin folder to the system path.
Oct 2, 2014 at 2:18 PM
That seems to have fixed it. I added both the the i386 and x64 bin locations to the SYSTEM path and the errors for loading the assemblies and functions has went away. now on to builder a better parser for the scripts. jperraud's sample web application has been very useful as a starting point - thanks for that! We're doing something similar here. We want to allow our users to to input their R scripts into a textbox (passing inputs from the previous step in the workflow) and then execute them, evaluate the results in the next phase of the work flow. Any graphs generated will then be attached to an email and sent back to the user with the results and/or any recommendations that are generated. If anyone has done anything similar, parsing R Scripts and mapping input and output variables with R.NET - Give a shout out, as there aren't a ton of examples out there.

Thanks again for the information for the previous issue!

sehunley
Measure Twice, Cut once...
Oct 2, 2014 at 2:30 PM
Excellent!
Dec 15, 2014 at 2:29 PM
Edited Mar 18, 2015 at 2:32 PM
I have almost exact problem, solved by adding R_Path and R_HOME to PATH.
Mar 23, 2015 at 8:17 AM
I am facing a similar problem as you. Can anyone please look at the following problem:

We have integrated R 3.1.2 with ASP.NET, by using R.NET plug in. But after deploying application in IIS 6.0, application is not able to call some of the R packages like "RODBC", "stats", etc. We are getting following error:

Error: Package or namespace load failed for stats.

The same error we are getting for package RODBC.
Mar 24, 2015 at 11:30 AM
Similar things happened to me before and it was quite troublesome. The error message is too lack of details.
There are several things you might wanna check first:
  1. install your packages in the default folder: C:\Program Files\R\R-3.1.3\library or define libpath when you load your packages
  2. set R_HOME as "C:\Program Files\R\R-3.1.2", R_PATH as "C:\Program Files\R\R-3.1.3\bin\i386" (or x64, depends on 32bit or 64bit process), add them to system PATH
  3. if you are loading java based packages, install 32bit or 64bit Java (same as your R), set JAVA_HOME to java bin folder, add it to system PATH
  4. restart IIS before you try again