[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