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.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