[Rd] checking user interrupts in C(++) code

Simon Urbanek simon.urbanek at r-project.org
Wed Sep 29 17:47:37 CEST 2010


On Sep 29, 2010, at 11:34 AM, Berwin A Turlach wrote:

> G'day Simon,
> 
> since Karl brought up this topic, I thought I might use it to seek
> clarification for something that bothered me for some time.
> 
> On Tue, 28 Sep 2010 14:55:34 -0400
> Simon Urbanek <simon.urbanek at r-project.org> wrote:
> 
>> There are several ways in which you can make your code respond to
>> interrupts properly - which one is suitable depends on your
>> application. Probably the most commonly used for interfacing foreign
>> objects is to create an external pointer with a finalizer - that
>> makes sure the object is released even if you pass it on to R later.
>> For memory allocated within a call you can either use R's transient
>> memory allocation (see Salloc) or use the on.exit handler to cleanup
>> any objects you allocated manually and left over.
> 
> But what about objects created by allocVector() or NEW_XXXX in C code
> that is called via .Call that need to be PROTECT'd?
> 

Any R objects are just fine because the protection stack gets unwound during cleanup. The whole point of PROTECT is that it protects the object for the duration of the call. On a clean exit you're responsible for the UNPROTECTing, for error handling exit R is responsible.


> The "Writing R Extensions" manual states:
> 
> 	The programmer is solely responsible for housekeeping the calls
> 	to @code{PROTECT}.  There is a corresponding macro
> 	@code{UNPROTECT} that takes as argument an @code{int} giving
> 	the number of objects to unprotect when they are no longer
> 	needed.  The protection mechanism is stack-based, so
> 	@code{UNPROTECT(@var{n})} unprotects the last @var{n} objects
> 	which were protected.  The calls to @code{PROTECT} and
> 	@code{UNPROTECT} must balance when the user's code returns.
> 	@R{} will warn about @code{"stack imbalance in .Call"} (or
> 	@code{.External}) if the housekeeping is wrong.
> 
> If a call to R_CheckUserInterrupt() may not return, does that mean that
> you should not call this function while you have objects PROTECT'd?
> 
> Even more, the section on R_CheckUserInterrupt() states:
> 
> 	Note that it is possible that the code behind one of the entry
> 	points defined here if called from your C or FORTRAN code could
> 	be interruptible or generate an error and so not return to your
> 	code.
> 
> This seems to imply that, if you have objects PROTECT'd in your code,
> you shouldn't use any of the R API defined in Chapter 6 of the manual,
> except if you know that it doesn't call R_CheckUserInterrupt(), and
> there seems to be no documentation on which functions in the API do and
> which don't.
> 

Nope, R_CheckInterrupt is just like any other R function - it may never return - but if it doesn't it cleans up everything R-related properly. The above R-ext note just tells you that your own stuff will need cleaning. R_CheckInterrupt is not really special in any way - for all practical purposes it behaves just like any other R API call and the same rules apply.

Cheers,
Simon


> I guess my question is, essentially, does the PROTECT mechanism and
> R_CheckUserInterrupt() play together nicely?  Can I call the latter
> from code that has objects PROTECT'd?  If yes, and the code gets
> interrupted, is the worse that happens a warning about a stack
> imbalance, or will the R session become "unusable/unstable"?
> 
> Thanks in advance for any enlightening comments.
> 
> Cheers,
> 
> 	Berwin
> 
> 



More information about the R-devel mailing list