From baier at ci.tuwien.ac.at  Wed May  7 09:14:20 2003
From: baier at ci.tuwien.ac.at (Thomas Baier)
Date: Wed May  7 08:14:57 2003
Subject: [Rd] R-1.7.0: Rproxy.dll loadlibrary/freelibrary error (PR#2914)
In-Reply-To: <2kdfbv4g3k9gl5fle6dm1rmpgr39csmc37@4ax.com>
Message-ID: <200305070614.h476EKnn000717@luthien.ci.tuwien.ac.at>

> Venkatesh:
> 
> I was hoping someone else would pick up on this one.  I don't know the
> rproxy code at all, so I can't tell if the error you are seeing is
> some new error in R or a mistake on your part.  I've cc'd this to
> Thomas Baier; Thomas, can you comment on this?
> 
> Venkatesh, you do mention a "huge leakage difference".  Could you
> expand on that, and maybe give a loop in plain R code that causes R to
> grow without bounds?

Just had a look at the code (but no further analysis at the moment).

What you're trying to do is you load and unload the library some times.
This is something you normally shouldn't do ;-)

1. Windows has some problems in releasing all memory of a DLL. Just
   loading and unloading a DLL (just containing text resources, no code
   at all) causes a memory leak (and a significant delay in time)
2. R itself assumes (or that's what I think) that all resources which are
   not explicitly freed are released by the operating system when R quits

Of course, you're right, that this could be a problem (the current implemen-
tation of the COM server loads the DLL in Init() and unloads in Terminate()).
But on the other hand, the COM server also gets terminated after the reference
to the COM object is released and every client gets a new server process.

If R 1.6.2 doesn't behave the same as you stated, there may be some newly
allocated resources which don't get freed (maybe statics which you can only
handle safely in an atexit() routine).

The question to Duncan now is if you are aware of any resources which can/should
be freed by rproxy.dll or by R. Anything we can do about it.

Venkatesh: Maybe you can just keep a single reference to the proxy object
so you won't hit the problem. Or use the COM server, which will automatically
handle this for you (out of process).

Best,
Thomas

> Duncan Murdoch
> 
> On Mon, 5 May 2003 01:07:30 +0200 (MET DST), you wrote in message
> <200305042307.h44N7U2b006301@pubhealth.ku.dk>:
> 
> >Full_Name: Venkatesh Mysore
> >Version: R-1.7.0
> >OS: WindowsXP
> >Submission from: (NULL) (216.165.110.10)
> >
> >
> >While accessing Rproxy.dll repeatedly (using the code from the (D)COM example in
> >the R website) causes a failure in the 24th iteration. R-1.6.2 does NOT give
> >this error. This seems to be a memory management error, that might be linked to
> >the huge leakage difference between R-1.7.0 and R-1.6.2 (leakage observed using
> >Windows Task Manager).
> >
> >Here is a C program that can be used to reproduce the error:
> >(the files SC-Proxy.h, Defn.h, Rinternals.h etc.. are to be included in the path
> >- see StatConnector.cpp in the (D)COM server example)
> >
> >
> >#include "windows.h"
> >#include "stdio.h"
> >#include "SC_Proxy.h"
> >#define RDLL "Rproxy.dll"
> >struct _SC_Proxy_Object* m_ProxyObject;
> >HMODULE m_ProxyModule;
> >
> >
> >#define SERVER_MAJOR_VERSION  "1"
> >#define SERVER_MINOR_VERSION "2"
> >
> >#define	SCN_IERR_INTERFACENOTFOUND      0x81000000
> >#define	SCN_IERR_LIBRARYNOTFOUND        0x81000001
> >#define	SCN_IERR_INVALIDLIBRARY         0x81000002
> >#define	SCN_IERR_INITIALIZATIONFAILED   0x81000003
> >#define	SCN_IERR_INVALIDCONNECTORNAME   0x81000004
> >#define SCN_ERR_INITIALIZED             0x81000005
> >#define SCN_ERR_NOTINITIALIZED          0x81000006
> >
> >#define TRACEBUFSIZE 1024
> >// 00-02-18 | baier | support arguments for connector initialization
> >// 01-04-04 | baier | enhancements by BDR: set RHOME from registry
> >// 03-04-07 | baier | check registry key on failure even if R_HOME is set,
> >//                    check PATH if everything else fails. trace failures!
> >int loadDll()
> >{
> >	  static char lTraceBuffer[TRACEBUFSIZE];
> >     // get entry-point
> >	if (getenv ("R_HOME"))
> >	  { // BDR
> >		  OutputDebugString("from env:");
> >		  char DLLlocation[MAX_PATH];
> >		  strcpy(DLLlocation, getenv("R_HOME"));
> >		  strcat(DLLlocation, "\\bin\\");
> >		  strcat(DLLlocation, RDLL);
> >		  OutputDebugString(DLLlocation);
> >		  m_ProxyModule = LoadLibraryEx (DLLlocation, NULL, 
> >					 LOAD_WITH_ALTERED_SEARCH_PATH);
> >		  // trace failure!
> >		  if (m_ProxyModule == 0) {
> >			  sprintf(lTraceBuffer,"R_HOME set to \"%s\", failed to load \"%s\"\n",
> >				  getenv("R_HOME"),DLLlocation);
> >			  OutputDebugString(lTraceBuffer);
> >		  }
> >	  }
> >
> >      if (m_ProxyModule == 0)
> >	  {
> >	  // look in the registry
> >	  OutputDebugString("from reg:");
> >	  char DLLlocation[MAX_PATH];
> >	  LONG rc;
> >	  HKEY hkey;
> >	  DWORD keytype = REG_SZ;
> >	  DWORD cbData = sizeof (DLLlocation);
> >	  rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\R-core\\R", 0, 
> >			     KEY_READ, &hkey);
> >	  if (rc == ERROR_SUCCESS)
> >	    {
> >	      rc = RegQueryValueEx (hkey, "InstallPath", 0, &keytype, 
> >				    (LPBYTE)DLLlocation, &cbData);
> >	      RegCloseKey (hkey);
> >	    }
> >
> >	  if (rc == ERROR_SUCCESS)
> >	    {
> >	      // set R_HOME
> >	      char *buf;
> >	      buf =
> >		(char *) malloc ((strlen (DLLlocation) + 8) * sizeof (char));
> >	      strcpy (buf, "R_HOME=");
> >	      strcat (buf, DLLlocation);
> >	      putenv (buf);
> >	      //SetEnvironmentVariable ("R_HOME",DLLlocation);
> >	      strcat (DLLlocation, "\\bin\\");
> >		  strcat (DLLlocation, RDLL);
> >		  OutputDebugString(DLLlocation);
> >	      m_ProxyModule = LoadLibraryEx (DLLlocation, NULL, 
> >					     LOAD_WITH_ALTERED_SEARCH_PATH);
> >	      if (m_ProxyModule == 0) {
> >		sprintf(lTraceBuffer,"Registry information said to load \"%s\", failed!\n",
> >		        DLLlocation);
> >		OutputDebugString(lTraceBuffer);
> >	      }
> >	    }
> >	  } //module==0
> >
> >	//m_ProxyModule = LoadLibraryEx ("C:\\R\\rw1070\\bin\\Rproxy.dll", NULL, 
> >	//				 LOAD_WITH_ALTERED_SEARCH_PATH);
> >
> >	
> >
> >      SC_PROXY_GET_OBJECT lFunc;
> >      
> >      lFunc = (SC_PROXY_GET_OBJECT) GetProcAddress (m_ProxyModule,
> >    						   SC_PROXY_GET_OBJECT_FUN);
> >	  
> >      
> >      if (lFunc == 0)
> >    	{
> >          return -1;
> >    	}
> >      
> >      // get proxy object
> >      ULONG lRc = lFunc (&m_ProxyObject,SC_PROXY_INTERFACE_VERSION);
> >      
> >	  
> >      if ((lRc != SC_PROXY_OK) || (m_ProxyObject == 0))
> >    	{
> >    	  FreeLibrary (m_ProxyModule);
> >    	  m_ProxyModule = 0;
> >    	  
> >          return -2;
> >    	}
> >      
> >      char* lParams = 0;
> >
> >	lParams = strdup ("");
> >	OutputDebugString("vtbl->init getting called:");         
> >      // init R
> >      lRc = m_ProxyObject->vtbl->init (m_ProxyObject,lParams);
> >	OutputDebugString("done init.");      
> >      free (lParams);
> >
> >      if (lRc != SC_PROXY_OK)
> >    	{
> >    	  m_ProxyObject->vtbl->release (m_ProxyObject);
> >    	  m_ProxyObject = 0;
> >    	  FreeLibrary (m_ProxyModule);
> >    	  m_ProxyModule = 0;
> >    	  
> >    	  return -3;
> >    	}
> >    return 1;
> >}
> >
> >int unloadDll()
> >{
> >
> >      m_ProxyObject->vtbl->release (m_ProxyObject);
> >	  m_ProxyObject = 0;
> >
> >	  DWORD err;
> >      int b = FreeLibrary (m_ProxyModule);
> >	  if (b==0) {
> >		  err = GetLastError();
> >		char ss[100];
> >		sprintf(ss,"\n\nErr = %d\n\n", err);
> >		OutputDebugString(ss);
> >		return -1;
> >	  } else OutputDebugString("no error unloading Rproxy dll.\n\n");
> >
> >	  m_ProxyModule = 0;
> >    
> >  return 1;
> >}
> >
> >
> >int main() {
> >	char ss[100];
> >	int i,x,a;
> >	for (i=1; i<=100; i++) {
> >		sprintf(ss,"Iteration: %d", i);
> >		OutputDebugString(ss);
> >	x=loadDll();
> >	if (x<=0) OutputDebugString("LoadLibraryEx ERROR.");
> >	else OutputDebugString("LoadLibraryEx succeeded.");
> >	a = unloadDll();
> >	if (a<=0) OutputDebugString("FreeLibrary ERROR.");
> >	else OutputDebugString("FreeLibrary succeeded.");
> >	}
> >}
> >
> >-----------------------------------------
> >
> >-Venkatesh Mysore
> >Bioinformatics Group,
> >New York University
> >
> >______________________________________________
> >R-devel@stat.math.ethz.ch mailing list
> >https://www.stat.math.ethz.ch/mailman/listinfo/r-devel
> 
> 

-- 
Thomas Baier


[Rd] R-1.7.0: Rproxy.dll loadlibrary/freelibrary error (PR#2914)
Thomas Baier