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.urba...@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@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> >> > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel