[Rd] clean-up actions after non-local exits

Luke Tierney luke at stat.uiowa.edu
Tue Apr 15 01:57:27 CEST 2008


On Mon, 14 Apr 2008, Vadim Organovich wrote:

> This is good, thanks!
>
> I'd like to be able to make sure that the resource is released in conrolled fasion rather than at some arbitrary gc() call time. Will the following trick achieve the goal:
>
> foo <-function(whatever) {
> on.exit(gc())
> ## arrange for an external pointer, don't know how yet
> ...
> ## actual call
> .Call(whatever)
> }
>
> The idea is to have gc() called on exit.
>
> I seem to recall that a call to gc() doesn't guarantee that all possibly collectable objects are actually collected, which will defeat my solution. Is that correct?

It would not be safe to rely on gc runing the finalizer at precisely
this time.  Probably it does now, but that may not always remain true.

If you are prepared to use R level wrappers with on.exit code, or
tryCatch with a finally clause, the I would use those to call your
cleanup code directly.  That is nearly guaranteed to succeed.  The
exception is that it is currently possible for a user interrupt (or a
timer interrupt in R 2.7 and up) to be handled in the running of the
interpreted part of the on.exit/finally code.  At some point there
will be an R-level mechanism for selectively disabling and then
re-enabling interrupts (and maybe that will be used by default in
conjunction with tryCatch or on.exit, but that needs thinking
though).  Until then if you need a stronger guarantee I would add the
finalizer option as a backup and let the GC call it when it gets to
it.

luke


>
> Thanks,
> Vadim
>
> ________________________________________
> From: Duncan Murdoch [murdoch at stats.uwo.ca]
> Sent: Monday, April 14, 2008 3:53 PM
> To: Vadim Organovich
> Cc: r-devel at r-project.org
> Subject: Re: [Rd] clean-up actions after non-local exits
>
> On 14/04/2008 4:33 PM, Vadim Organovich wrote:
>> Dear R-devel,
>>
>>
>>
>> Some time ago I started a thread that boiled down to clean-up actions after non-local exits in R, see below. I wonder if there has been any progress on this? R-ext 2.6.1 doesn't say much on the subject.
>>
>>
>>
>> How, for example, do people deal with a situation where their C (C++) function opens a file and then receives a signal or  longjump-s on error(), how do they make sure the file is eventually closed?
>
> The finalizer code that Luke mentioned is more easily accessible now
> than it was in 2004.  See the section on external pointers and weak
> references in the Writing R Extensions manual.
>
> The idea would be to create an external pointer object that controls the
> resource.  If there's an error, at the next GC the external pointer will
> be finalized and that's where the cleanup can happen.
>
> Duncan Murdoch
>
>>
>>
>> Thanks,
>>
>> Vadim
>>
>>
>>
>> On Mon, 14 Jun 2004, Vadim Ogranovich wrote:
>>
>>> This is disappointing. How on Earth can mkChar know when it is safe or
>>> not to make a long jump? For example if I just opened a file how am I
>>> supposed to close it after the long jump? I am not even talking about
>>> C++ where long jumps are simply devastating... (and this is the language
>>> I am coding in :-( )
>>>
>>> Ok. A practical question: is it possible to somehow block
>>> R_CheckUserInterrupt? I am ready to put up with out-of-memory errors,
>>> but Ctrl-C is too common to be ignored.
>>
>> Interrupts are not the issue. The issue is making sure that cleanup
>> actions occur even if there is a non-local exit. A solution that
>> addresses that issue will work for any non-local exit, whether it
>> comes from an interrupt or an exception. So you don't have to put up
>> with anything if you approach this the right way,
>>
>> Currently there is no user accessible C level try/finally mechanism
>> for insuring that cleanup code is executed during a non-local exit.
>> We should make such a mechanicm available; maybe one will make it into
>> the next major release.
>>
>> For now you have two choices:
>>
>>     You can create an R level object and attach a finalizer to the object
>>     that will arrange for the GC to close the file at some point in the
>>     future if a non-local exit occurs. Search developer.r-project.org for
>>     finalization and weak references for some info on this.
>>
>>     One other option is to use the R_ToplevelExec function. This has some
>>     drawbacks since it effectively makes invisible all other error
>>     handlers, but it is an option. It is also not officially documented
>>     and subject to change.
>>
>>> And I think it makes relevant again the question I asked in another
>>> related thread: how is memory allocated by Calloc() and R_alloc() stand
>>> up against long jumps?
>>
>> R_alloc is stack-based; the stack is unwound on a non-local exit, so
>> this is released on regular exits and non-local ones. It uses R
>> allocation, so it could itself cause a non-local exit.
>>
>> Calloc is like calloc but will never return NULL. If the allocation
>> fails, then an error is signaled, which will result in a non-local
>> exit. If the allocation succeeds, you are responsable for calling
>> Free.
>>
>> luke
>>
>>>> -----Original Message-----
>>>> From: Luke Tierney [mailto:luke at stat.uiowa.edu<mailto:luke at stat.uiowa.edu?Subject=RE:%20%5BR%5D%20mkChar%20can%20be%20interrupted>]
>>>> Sent: Monday, June 14, 2004 5:43 PM
>>>> To: Vadim Ogranovich
>>>> Cc: R-Help
>>>> Subject: RE: [R] mkChar can be interrupted
>>>>
>>>> On Mon, 14 Jun 2004, Vadim Ogranovich wrote:
>>>>
>>>>> I am confused. Here is an excerpt from R-exts:
>>>>>
>>>>> "As from R 1.8.0 no port of R can be interrupted whilst
>>>> running long
>>>>> computations in compiled code,..."
>>>>>
>>>>> Doesn't it imply that the primitive functions like allocVector,
>>>>> mkChar, etc., which are likely to occur in any compiled code called
>>>>> via .Call, are not supposed to handle interrupts in any way?
>>>> No it does not. Read the full context. It says that if you
>>>> wite a piece of C code that may run a long time and you want
>>>> to guarantee that users will be able to interrupt your code
>>>> then you should insure that R_CheckUserInterrupt is called
>>>> periodically. If your code already periodically calls other
>>>> R code that checks for interrupts then you may not need to do
>>>> this yourself, but in general you do.
>>>>
>>>> Prior to 1.8.0 on Unix-like systems the asynchronous signal
>>>> handler for SIGINT would longjmp to the nearest top level or
>>>> browser context, which meant that on these sytems any code
>>>> was interruptible at any point unless it was explicitly
>>>> protected by a construct that suspended interrupts. Allowing
>>>> interrupts at any point meant that inopportune interrupts
>>>> could and did crash R, which is why this was changed.
>>>>
>>>> Unless there is explicit documentation to the contrary you
>>>> should assume that every function in the R API might allocate
>>>> and might cause a non-local exit (i.e. a longjmp) when an
>>>> exception is raised (and an interrupt is one of, but only one
>>>> of, the exceptions that might occur).
>>>>
>>>> luke
>>>>
>>>>> Thanks,
>>>>> Vadim
>>>>>
>>>>>
>>>>>> From: Luke Tierney [mailto:luke at stat.uiowa.edu<mailto:luke at stat.uiowa.edu?Subject=RE:%20%5BR%5D%20mkChar%20can%20be%20interrupted>]
>>>>>>
>>>>>> On Mon, 14 Jun 2004, Vadim Ogranovich wrote:
>>>>>>
>>>>>>>> From: Luke Tierney [mailto:luke at stat.uiowa.edu<mailto:luke at stat.uiowa.edu?Subject=RE:%20%5BR%5D%20mkChar%20can%20be%20interrupted>]
>>>>> ...
>>>>>>>> Not sure why you think this suggest mkChar can be interrupted.
>>>>>>>>
>>>>> ...
>>>>>>>> by calls to this function. I don't believe there are any
>>>>>> such safe
>>>>>>>> points in mkChar, but there are several potential ones
>>>>>> within your
>>>>>>>> example.
>>>>>>> Apart from mkChar I am only calling SET_STRING_ELT. Is this
>>>>>> what you
>>>>>>> mean?
>>>>>> You are printing, you have an assignment expression, all of those
>>>>>> contain points where an interrupt could be checked for.
>>>>> These are not relevant since Ctrl-C is pressed when the
>>>> code is inside
>>>>> for (i=0; i<n; ++i) {
>>>>> SET_STRING_ELT(resSexp, i, mkChar("foo"));
>>>>> }
>>>>>
>>>>> Just look at the way I deliver the signal.
>>>>>
>>>>> ______________________________________________
>>>>> R-help at stat.math.ethz.ch<mailto:R-help at stat.math.ethz.ch?Subject=RE:%20%5BR%5D%20mkChar%20can%20be%20interrupted> mailing list
>>>>> https://www.stat.math.ethz.ch/mailman/listinfo/r-help
>>>>> PLEASE do read the posting guide!
>>>>> http://www.R-project.org/posting-guide.html<http://www.r-project.org/posting-guide.html>
>>>>>
>>>> --
>>>> Luke Tierney
>>>> University of Iowa Phone: 319-335-3386
>>>> Department of Statistics and Fax: 319-335-3017
>>>> Actuarial Science
>>>> 241 Schaeffer Hall email: luke at stat.uiowa.edu<mailto:luke at stat.uiowa.edu?Subject=RE:%20%5BR%5D%20mkChar%20can%20be%20interrupted>
>>>> Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu<http://www.stat.uiowa.edu/>
>>>>
>>>>
>>>>
>>> ______________________________________________
>>> R-help at stat.math.ethz.ch<mailto:R-help at stat.math.ethz.ch?Subject=RE:%20%5BR%5D%20mkChar%20can%20be%20interrupted> mailing list
>>> https://www.stat.math.ethz.ch/mailman/listinfo/r-help
>>> PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html<http://www.r-project.org/posting-guide.html>
>>>
>>
>> --
>> Luke Tierney
>>
>>
>>       [[alternative HTML version deleted]]
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

-- 
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:      luke at stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu



More information about the R-devel mailing list