On Apr 25, 2011, at 11:09 AM, schattenpfla...@arcor.de wrote:
Thank you for your response, Simon.
1. Calling R_CheckUserInterrupt() interrupts immediately, so
I have no possibility to exit my code gracefully. In
particular, I suppose that objects created on the heap (e.g.,
STL containers) are not destructed properly.
In general, you're responsible for the cleanup. See R-devel
archives for discussion on the interactions of C++ and R error
handling. Generally, you should not use local objects and you
should use on.exit to make sure you clean up.
I am using Rcpp (Rcpp-modules, to be precise). This means, I do
actually not write any R code. Moreover, the C++ code does not
use the R API. My C++ functions are 'exposed' to R via Rcpp,
which creates suitable S4 classes. Rcpp does the exception
handling. In particular, there is no obvious possibility for me
to add an 'on.exit' statement to a particular exposed C++
method.
Generally, you should not use local objects
We are talking about large amounts of code, dozens of nested
function calls, and even external libraries. So "not using local
objects" is definitely no option.
But that would imply that the library calls R! Note that we're
talking about the stack at the point of R API call, so you can do
what you want until you cal R API. At the moment you touch R API
you should have no local C++ objects on the stack (all the way
down) - that's what I meant.
2. Calling R_CheckUserInterrupt() within a parallel OpenMP
loop causes memory corruptions. Even if I do so within a
critical section, it usually results in segfaults, crashes,
or invalid variable contents afterwards. I suppose this is
due to the threads not being destroyed properly. Since most
of the time critical computations are done in parallel, this
means I can hardly interrupt anything.
As you know R is not thread-safe so you cannot call any R API
from a thread - including OMP threads - so obviously you can't
call R_CheckUserInterrupt().
That is very interesting. Not being thread safe does not
necessarily imply that a function cannot be called from within a
thread (as long as it is not done concurrently from several
threads). In particular, the main program itself is also a
thread, isn't it?
Yes, but each thread has a separate stack, and you can only enter R
with the same stack you left (because the stack will be restored to
the state of the calling context).
Since no cleanup is done, however, it is now clear that calling
R_CheckUserInterrupt() _anywhere_ in my program, parallel section
or not, is a bad idea.
Since you're using threads the safe way is to perform your
computations on a separate thread and let R handle events so
that you can abort your computation thread as part of on.exit.
Starting the computations in a separate thread is a nice idea. I
could then call R_CheckUserInterrupt() every x milliseconds in
the function which dispatches the worker thread. Unfortunately, I
see no obvious way of adding an "on.exit" statement to an Rcpp
module method. So I would probably have to call an R function
from C++ (e.g., using RInside) which contains the on.exit
statement, which in turn calls again a C++ function setting a
global 'abort' flag and waits for the threads to be terminated.
Hmmm.
How does on.exit work?
It sets the conexit object of the current context structure to the
closure to be evaluated when the context is left. endcontext() then
simply evaluates that closure when the context is left.
Could I mimic that behaviour directly in C++?
Unfortunately there is no C-level onexit hook and the internal
structure of RCNTXT is not revealed to packages. So AFAICS the
closest you can get is to use eval to call on.exit().
However, I think it would be useful to have a provision for
creating a context with a C-level hook - the question is whether
the others have the feeling that it's going to a too low level ...
Having a function similar to R_CheckUserInterrupt() but
returning a boolean variable (has an interrupt occurred or
not?) would solve these problems. Is there a way to find out
about user interrupt requests (the user pressing ctrl+c or
maybe a different set of keys) without interrupting
immediately?
Checking for interrupts may involve running the OS event loop
(to allow the user to interact with R) and thus is not
guaranteed to return.
I see.
There is no general solution - if you're worried only about
your, local code, then on unix, for example, you could use
custom signal handlers to set a flag and co-operatively
interrupt your program. On Windows there is the UserBreak flag
which can be set by a separate thread and thus you may check on
it. That said, all this is very much platform-specific.
Being able to set a flag is all I need and would be the perfect
solution imho. However, I do not yet see how I could achieve
that.
It is GUI-specific, unfortunately. AFAIR the Windows GUI does that
because it's running on a separate thread. I think the X11-based
GUIs use fds so the are synchronous and on OS X runs the OS loop
inside the R event loop - so, again, synchronous.
How can I write a signal handler within C++ code which does not
create a GUI and has no dedicated event dispatching thread?
That's simple just use signal() to register your handler.
Would it be possible to use, e.g., a Qt keyboard event handler
within the C++ code? Would a keyboard event be visible to such an
event handler? Is it not intercepted by R / the terminal window /
the OS?
Meshing R's loop, GUI loop and your own code will be a nightmare.
For example, one problem is that if you are running the GUI loop
and it triggers an event that R would otherwise handle (e.g.
resizing plot window) you're in trouble since you can't let R do
anything...
Does any existing R package contain signal handlers?
I'm not sure - I would definitely not recommend that to be used in
packages since it's platform-dependent and changes the semantics of
signals defined by R. But you can play with it ;).
Cheers, Simo