[Rd] Overriding InitTempDir

Jeffrey Horner jeff.horner at vanderbilt.edu
Fri Sep 1 21:09:22 CEST 2006

Prof Brian Ripley wrote:
> It is conventional for people proposing changes to R to set out a 
> compelling case as to why they are needed.  I have not seen any case here.
> Can we please have one?

Here's the case for RApache:

An Apache server built with the prefork multi-processing module creates 
and destroys many processes, and if it loads the RApache module, this 
means that each server process initializes its own R interpreter, 
thereby creating many new temp directories. Now, the Apache API provides 
shutdown hooks to allow modules (such as with RApache) to do cleanup 
work, e.g. remove temporary directories, before a process is destroyed, 
but there are occasions when processes just die. I'd like RApache to 
fail a little more gracefully, in this case, by not leaving around a 
(usually empty) temp directory.

> Someone will have to think through the ramifications of such a change (and 
> BTW using edit() in an R console is not at all unlikely), and continue to 
> maintain it for years to come.  I have to say that in the past I have 
> accepted quite a few user suggestions that became maintenance nightmares, 
> so I have become very wary.

Understood, but I have to say that I'm even more confused about how a 
program that embeds R is expected to shut itself down with the 
introduction of Rf_endEmbeddedR. Does this implicitly deprecate the use 
of overriding the callback R_CleanUp?

> It's not really a good time: R-devel is about to start solidifying towards 
> 2.4.0, and we have quite a few issues to work through (e.g. the internal 
> changes to S4 methods).

Of course, that does seem a bit more important.

> On Fri, 1 Sep 2006, Jeffrey Horner wrote:
>> Jeffrey Horner wrote:
>>> For embedded projects, one may want to eliminate the per-session temp 
>>> directory created by InitTempDir() and just use a system-specific temp 
>>> directory. Here's my solution:
>>> extern char *R_TempDir;
>>> void my_InitTempDir()
>>> {
>>>      char *tmp;
>>>      if (R_TempDir){
>>>          if (rmdir(R_TempDir) != 0){
>>>              perror("Fatal Error: could not remove R's TempDir!");
>>>              exit(1);
>>>          }
>>>      }
>>>      tmp = getenv("TMPDIR");
>>>      if (tmp == NULL) {
>>>          tmp = getenv("TMP");
>>>              if (tmp == NULL) {
>>>                  tmp = getenv("TEMP");
>>>                  if (tmp == NULL)
>>>                      tmp = "/tmp";
>>>              }
>>>      }
>>>      R_TempDir=tmp;
>>>      if (setenv("R_SESSION_TMPDIR",tmp,1) != 0){
>>>          perror("Fatal Error: couldn't set/replace R_SESSION_TMPDIR!");
>>>          exit(1);
>>>      }
>>> }
>>> This function is called after Rf_initEmbeddedR; it's seems like a hack 
>>> but it works. Does anyone have other solutions?
>> I just found a fault with the above solution, but only if a program that 
>> embeds R calls the R edit function; highly unlikely. Nevertheless, It 
>> turns out that soon after InitTempDir is called, InitEd is called and 
>> sets the variable DefaultFileName (which is hidden by storage class 
>> static, unlike R_TempDir) to a temporary filename located in the 
>> directory which was just deleted by my_initTempDir.
>>> Maybe InitTempDir could check if R_TempDir was not NULL and then just 
>>> return.
>> So it would be nice if the above (InitTempDir only creating a directory 
>> when R_TempDir is NULL) could be added to R-trunk.
>> Note also that in the case that R_TempDir is set to a system-specific 
>> temp directory, the program would then have to set it back to NULL as 
>> the new function Rf_endEmbeddedR now tests to see if R_TempDir has been set:
>> /* use fatal !=0 for emergency bail out */
>> void Rf_endEmbeddedR(int fatal)
>> {
>>      unsigned char buf[1024];
>>      char * tmpdir;
>>      R_RunExitFinalizers();
>>      CleanEd();
>>      if(!fatal) KillAllDevices();
>>      if((tmpdir = R_TempDir)) {
>>      snprintf((char *)buf, 1024, "rm -rf %s", tmpdir);
>>      R_system((char *)buf);
>>      }
>>      if(!fatal && R_CollectWarnings)
>>      PrintWarnings();    /* from device close and .Last */
>>      fpu_setup(FALSE);
>> }
>> Jeff


More information about the R-devel mailing list