[Rd] Interrupting C++ code execution
Sean Robert McGuffee
sean.mcguffee at gmail.com
Tue Apr 26 23:06:02 CEST 2011
Hi,
I've been thinking about how to handle c++ threads that were started via
Rcpp calls to some of my c++ libraries from R. My main obstacle is trying to
make sure that users don't try to process files that are being generated by
a thread before the thread finishes. One thing I am considering is having my
threaded code return a class to R that contains a pointer that it remembers.
Then maybe I could just change the value at that pointer when my thread
finishes. Does that seem like a reasonable approach? I'm not completely sure
if this is related to your issue or not, but it might be similar enough to
be worth asking...
Thanks,
Sean
On 4/26/11 9:21 AM, "Simon Urbanek" <simon.urbanek at r-project.org> wrote:
>
> On Apr 26, 2011, at 7:30 AM, schattenpflanze at arcor.de wrote:
>
>> I have tested the solutions suggested by Simon and Thomas on a Linux machine.
>> These are my findings:
>>
>>> On Windows you can look at the variable "UserBreak", available from
>>> Rembedded.h. Outside of Windows, you can look at R_interrupts_pending,
>>> available from R_ext/GraphicsDevice.h. R_ext/GraphicsDevice.h also has
>>> R_interrupts_suspended, which you may or may not want to take into account,
>>> depending on your use-case.
>> I did not manage to get this to work. Neither R_interrupts_pending nor
>> R_interrupts_suspended seem to change when I press ctrl+c. Perhaps this is
>> due to the fact that I run R in a terminal without any graphical interface?
>>
>
> Thomas' suggestion was not aimed at your problem - it was sort of the inverse
> (more at your Qt question). If you want to interrupt R you can mess with those
> flags and them let R run the event loop. It doesn't work in your (original)
> case.
>
>
>>> static void chkIntFn(void *dummy) {
>>> R_CheckUserInterrupt();
>>> }
>>> // this will call the above in a top-level context so it won't longjmp-out
>>> of your context
>>> bool checkInterrupt() {
>>> return (R_ToplevelExec(chkIntFn, NULL) == FALSE);
>>> }
>>> // your code somewhere ...
>>> if (checkInterrupt()) { // user interrupted ... }
>> This solution works perfectly! It takes slightly longer to call this function
>> than the plan R_CheckUserInterrupt() call, but in any reasonable scenario,
>> the additional time is absolutely insignificant.
>>
>> Inside OpenMP parallel for constructs, one has to make sure that only the
>> thread satisfying omp_get_thread_num()==0 makes the call (the 'master'
>> construct cannot be nested inside a loop). I can then set a flag, which is
>> queried by every thread in every loop cycle, causing fast termination of the
>> parallel loop. After the loop, I throw an exception. Thus, my code is
>> terminated gracefully with minimal effort. I can do additional cleanup
>> operations (which usually is not necessary, since I use smart pointers), and
>> report details on the interrupt to the user.
>>
>> With my limited testing, so far I have not noticed any downsides. Of course,
>> there is the obvious drawback of not being supported officially (and thus
>> maybe being subject to change),
>
> Actually, it is in the official API (Rinternals.h) so I don't think that is
> the issue.
>
>
>> the question of portability, and the question of interoperability with other
>> errors.
>>
>
> It is portable as well, so I'd say the main concern is what happens when
> events trigger something that is not related to you and you eat those errors.
> They will act as user-interrupt to you even if it's not what the user
> intended. One could argue that it's the lesser of the evils, because if you
> don't do anything R will just block so those events would have to wait until
> you're done anyway.
>
>
>> Moreover, I have found an old thread discussing almost the same topic:
>> http://tolstoy.newcastle.edu.au/R/e4/devel/08/05/1686.html .
>> The thread was created in 2008, so the issue is not really a new one. The
>> solution proposed there is actually the same as the one suggested by Simon,
>> namely using R_ToplevelExec().
>>
>
> Interesting - I'm glad Luke also suggested C-level onexit bac then - it is
> something I was thinking about before ..
>
> Cheers,
> Simon
>
>
>> An officially supported, portable solution would of course be much
>> appreciated!
>>
>>
>> Best regards,
>> Peter
>>
>>
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list