[Rd] Capturing signals from within external libs

Jeffrey Ryan jeff.a.ryan at gmail.com
Wed May 23 18:40:59 CEST 2012


Simon,

Thanks for the clarifying example.  I fear my current set up fails the
test for 'no R calls', 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