[Rd] sending signals to embedded R
deepayan.sarkar at gmail.com
deepayan.sarkar at gmail.com
Mon May 7 02:57:04 CEST 2007
On 5/6/07, Jeffrey Horner <jeff.horner at vanderbilt.edu> wrote:
> Luke Tierney wrote:
[...]
> >> Is there a reason R_ProcessEvents cannot be set on Unix but can on
> >> Mac? It doesn't seem user-settable on Windows, but whatever the built
> >> in default is seems to handle the Qt event loop. And for that matter,
> >> why is it possible to set the file.edit callback on Mac but not Linux?
> >> This seems arbitrary, and no explanation is given (that I could find).
> >
> > The R_PRocessEvents callback may be settable on MacOS but I'm not sure
> > it's used -- at least a quick grep didn't reveal its use anywhere
> > outside the gnuwin32 code.
I meant the callback ptr_R_ProcessEvents (in Rinterface.h). The Mac
GUI source has (this is probably not the latest version):
dsarkar at kanika:~/Mac-GUI-1.17$ grep -i ptr_r_process */*
REngine/Rinit.c:extern void (*ptr_R_ProcessEvents)();
REngine/Rinit.c: ptr_R_ProcessEvents = Re_ProcessEvents;
and R/trunk/src/unix/aqua.c has:
void R_ProcessEvents(void)
{
if(!useaqua){
if (R_interrupts_pending)
onintr();
return;
} else
ptr_R_ProcessEvents();
}
> > It would be good to unify the Mac and *nix mechanisms here since the
> > OS underpinings are now so similar, but it will have to get high
> > enough on someone's priority list to happen.
[...]
> >> The problem I'm having with this solution is that whenever I interrupt
> >> a graphics command, R crashes. This is true for commands being
> >> evaluated by R_tryEval, but not those run from the REPL (for example,
> >> if I make the call inside a debug() environment, interrupting it
> >> causes no problems). As far as I can tell, this is only a problem with
> >> graphics; other commands can be interrupted even when run using
> >> R_tryEval().
> >
> > That sounds like a longjmp being done to a place that doesn't exist --
> > maybe a threading issue in Qt. See what gdb tells you about where the
> > crash is occurring. It might be different for onintr and kill. You
> > might also try just setting the R_interrupts_pending flag from the
> > interrupt event handler rather than calling onintr (which probably
> > longjmp's) or kill (which may be doing something you don't want if
> > other threads with other signal handlers are involved).
I will have to start learning about gdb sometime soon, but in this case, the
problem seems to be due to the interaction of R_tryEval() and
graphics, and has nothing to do with interruptions. Here's a variant
of the trEval test case that triggers a legitimate error caused by
grid.text('foo', gp = gpar(font=1, fontface=1))
dsarkar at kanika:~$ cat tryEvalGraphics.c ## beware of line wrapping
/*
Compile this as:
RPROG=R-devel
export LD_LIBRARY_PATH=`${RPROG} RHOME`/lib:\${LD_LIBRARY_PATH}
gcc `${RPROG} CMD config --cppflags` \
`${RPROG} CMD config --ldflags` \
-o tryEvalGraphics tryEvalGraphics.c
*/
#include <Rinternals.h>
#include <Rembedded.h>
#include <R_ext/Parse.h>
int
main(int argc, char *argv[])
{
SEXP e, val;
int i, errorOccurred;
ParseStatus status;
char *cmds[] = {
"library(lattice)",
"library(grid)",
"grid.text('foo', gp = gpar(font=1, fontface=1))",
"xyplot(1 ~ 1, panel = function() grid.text('foo', gp =
gpar(font=1, fontface=1)))"
};
argv[0] = "R";
Rf_initEmbeddedR(argc, argv);
for (i = 0; i < 4; i++) {
printf("** I **: Executing command: %s\n", cmds[i]);
fflush(stdout); sleep(1);
PROTECT(e = R_ParseVector(mkString(cmds[i]), -1, &status, R_NilValue));
val = R_tryEval(VECTOR_ELT(e, 0), NULL, &errorOccurred);
if (errorOccurred) { Rprintf("Error executing: %s\n", cmds[i]); }
else Rf_PrintValue(val);
UNPROTECT(1);
printf("** I **: Succeeded\n");
fflush(stdout); sleep(1);
}
Rf_endEmbeddedR(0);
return(0);
}
Running this, I get:
dsarkar at kanika:~$ R-devel CMD ./tryEvalGraphics
R version 2.6.0 Under development (unstable) (2007-05-04 r41439)
[...]
[Previously saved workspace restored]
** I **: Executing command: library(lattice)
[1] "stats" "graphics" "grDevices" "utils" "datasets" "lattice"
[7] "rcompgen" "methods" "base"
** I **: Succeeded
** I **: Executing command: library(grid)
[1] "grid" "stats" "graphics" "grDevices" "utils" "datasets"
[7] "lattice" "rcompgen" "methods" "base"
** I **: Succeeded
** I **: Executing command: grid.text('foo', gp = gpar(font=1, fontface=1))
Error in validGP(list(...)) : Must specify only one of 'font' and 'fontface'
Error executing: grid.text('foo', gp = gpar(font=1, fontface=1))
** I **: Succeeded
** I **: Executing command: xyplot(1 ~ 1, panel = function()
grid.text('foo', gp = gpar(font=1, fontface=1)))
Error in validGP(list(...)) : Must specify only one of 'font' and 'fontface'
*** caught segfault ***
address 0x22000440, cause 'memory not mapped'
Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
Selection: 3
dsarkar at kanika:~$
Note that the first error (which doesn't actually get around to
starting a device) is handled properly, while the second is not.
[...]
> Deepayan, this is your code from quter-20070502 below, where R_tryEval
> is called:
>
> PROTECT(cmdSexp = mkString(cmd));
> PROTECT(cmdExpr = R_ParseVector(cmdSexp, -1, &status, R_NilValue));
> if (status == PARSE_OK) {
> int i, errorOccurred;
> for(i = 0; i < length(cmdExpr); i++) {
> ans = R_tryEval(VECTOR_ELT(cmdExpr, i),
> NULL, &errorOccurred);
> }
> if (errorOccurred) ans = R_NilValue;
> UNPROTECT(2);
>
> Question: is each element of cmdExpr actually on the protection stack?
> Or rather, is the caller guaranteed that the cmdExpr element will not be
> garbage collected? My assumption is yes, since cmdExpr is, but I could
> be wrong.
Normally I would say yes, because my understanding is that
sub-elements of protected SEXP's are supposed to be automatically
protected. But I don't really know what happens when there is an
error. On the other hand, I haven't been seeing any errors (other than
the graphics one described above) recently with that code.
One possibly relevant factoid: a few days ago I was trying to play
with R_topLevelExec(), and that seemed to require an extra UNPROTECT()
for no reason (there's a similar hack in rkward). I sort of got it
working, but two consecutive errors reproducibly took me to a
situation where the same error message would get repeated whatever I
did after that. I didn't pursue this because I figured out an
alternative solution to my problem.
-Deepayan
> Just curious because I just ran into troubles with calling
> R_tryEval with unprotected expressions and accepting signals. I
> witnessed what Luke explained above, that longjmp's were being done to a
> place that I wasn't anticipating, e.g. R_tryEval was never returning.
>
> Jeff
More information about the R-devel
mailing list