[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
>>
>
--
http://biostat.mc.vanderbilt.edu/JeffreyHorner
More information about the R-devel
mailing list