checking user interrupts in C(++) code
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