[Rd] Capturing signals from within external libs

Simon Urbanek simon.urbanek at r-project.org
Wed May 23 18:49:33 CEST 2012


On May 23, 2012, at 12:40 PM, Jeffrey Ryan wrote:

> Simon,
> 
> Thanks for the clarifying example.  I fear my current set up fails the
> test for 'no R calls',

Well, but in that case you already have interrupt points so I'm not sure what is the problem? I thought the whole point is that you have long processing in some 3rd party library where you can't call R API so that's why you need the hack in the first place ...


> so I think I am stuck on the ugly variant for my
> current challenge, but I will be able to use this in other places.
> 
> Thanks again,
> Jeff
> 
> On 5/22/12 4:45 PM, "Simon Urbanek" <simon.urbanek at r-project.org> wrote:
> 
>> Jeff,
>> 
>> On May 22, 2012, at 4:31 PM, Jeffrey Ryan wrote:
>> 
>>> I have a continuous loop running in an external library that I am
>>> calling
>>> from C (R API).  This loop is processing events in real time with the
>>> possibility of significant lag between events.
>>> 
>>> When processing an event, I can make use of R_CheckUserInterrupt, but
>>> while the external library code is waiting on a new event, I don't have
>>> an
>>> opportunity to call this - my entry points are only on events.
>>> 
>> 
>> Assuming that while in the library there are no R calls (important!), you
>> can use setjmp/longjmp to branch your code depending on whether you raise
>> an interrupt or not (see below). This also makes sure that you process
>> things on the R side properly
>> 
>> Another alternative is to run your library call on a separate thread and
>> have R wait for the result. In that case you don't need to mess with
>> interrupts since your library code will run separately from R. The
>> downside is that you need to mess with threads which may or may not be an
>> issue depending on the complexity of your code and whether you want it to
>> be cross-platform or not.
>> 
>> Cheers,
>> Simon
>> 
>> 
>> Example code:
>> 
>> #include <signal.h>
>> #include <setjmp.h>
>> #include <unistd.h>
>> 
>> #include <Rinternals.h>
>> #include <R_ext/GraphicsEngine.h> /* only needed if you use
>> R_interrupts_pending */
>> 
>> static jmp_buf jenv;
>> 
>> static void my_int(int sig) {
>> longjmp(jenv, 1); /* this also restores the interrupt handlers */
>> }
>> 
>> SEXP my_R_function(...) {
>> 
>> if (setjmp(jenv) == 0) { /* enter your protected code */
>> void (*old_sig)(int);
>> old_sig = signal(SIGINT, my_int);
>> /* call your library here */
>> /* restore original INT handler */
>> signal(SIGINT, old_sig);
>> } else { /* this will get called on interrupt */
>> /* you can do what you want - you're back to R-safe code here, so you
>> can either raise an error or return from your function */
>> /* if you want to trigger regular R interrupt handling, use this: */
>>  R_interrupts_pending = 1;
>>  R_CheckUserInterrupt();
>> /* the above should not return */
>> }
>> 
>> 
>> 
>>> I can capture a SIGINT by redefining signal(SIGINT, myhandler) before
>>> calling the lib, but I am somewhat at a loss in terms of what I can do
>>> within the handler that would let me pass control back to R.
>>> 
>>> void myhandler (int s) {
>>> error("interrupt caught!");
>>> }
>>> 
>>> Works, but I am sure it isn't supposed to.  In fact I know it is wrong,
>>> since after interrupting once SIGINTs are subsequently ignored, even if
>>> I
>>> reset the signal to the original one (as returned by the first call to
>>> signal).
>>> 
>>> Currently I can exit(1) of course, but that is tragically bad form IMO,
>>> though will work in my situation.
>>> 
>>> In short, what is the proper way to handle SIGINT in external code that
>>> is
>>> called from R, that allows R to handle the signal.  Thoughts or
>>> suggestions appreciated.
>>> 
>>> Thanks,
>>> Jeff
>>> 
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>> 
>>> 
>> 
> 
> 
> 



More information about the R-devel mailing list