[Rd] problem with findFun call from embedded R
Byron Ellis
byron.ellis at gmail.com
Thu Jul 5 02:34:23 CEST 2007
Yeah, setting R_Interactive is probably fine. I do it (not that I
should be considered a "safe" user of R). As to the findFun issue,
there is a much more useful function (findVar1 maybe?) that wouldn't
die if the object didn't exist.
Sadly, like many functions useful for the development of user
interfaces and embedding R have been marked "hidden" making them
unavailable for use without building a custom version of R.
On 7/4/07, Joe Conway <mail at joeconway.com> wrote:
> I was debugging a problem reported to me regarding PL/R, and found that
> I can duplicate it using only R sources. It might be characterized as
> possibly a misuse of the findFun() function, but I leave that for the R
> devel experts to decide.
>
> The below results are all with R-2.5.1 (I can't seem to download
> r-patched at the moment, but didn't see anything in the 2.5.1-patched
> release notes indicating this issue had been noticed) on Fedora Core 6
> x86_64 (also duplicated with R-2.5.0 on FC7 i386).
>
> Steps to reproduce:
> 8<------------------------
> configure, make, make install from source tree
> cd tests/Embedding/
> make RNamedCall
> ./RNamedCall #works as expected
> mv foo.R foo.R.orig
> ./RNamedCall #segfaults
> 8<------------------------
>
> output:
> 8<------------------------
> Error in file(file, "r", encoding = encoding) :
> unable to open connection
> In addition: Warning message:
> cannot open file 'foo.R', reason 'No such file or directory' in:
> file(file, "r", encoding = encoding)
> Error: could not find function "foo"
>
> *** caught segfault ***
> address (nil), 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: 1
> aborting ...
> Segmentation fault
> 8<------------------------
>
> The problem comes from RNamedCall starting at line 54:
> 8<------------------------
> fun = findFun(install("foo"), R_GlobalEnv);
> if(fun == R_NilValue) {
> fprintf(stderr, "No definition for function foo.
> Source foo.R and save the session.\n");
> UNPROTECT(1);
> exit(1);
> }
> 8<------------------------
>
> If foo.R was not found and never sourced, meaning that the object "foo"
> does not exist, findFun never returns. Instead the segfault occurs at
> line 719 in errors.c at the LONGJMP statement. Setting a breakpoint at
> erros.c:719, the backtrace looks like this (will wrap poorly):
>
> 8<------------------------
> Breakpoint 2, jump_to_top_ex (traceback=TRUE, tryUserHandler=TRUE,
> processWarnings=TRUE, resetConsole=TRUE,
> ignoreRestartContexts=FALSE) at errors.c:719
> 719 LONGJMP(R_ToplevelContext->cjmpbuf, 0);
> (gdb) bt
> #0 jump_to_top_ex (traceback=TRUE, tryUserHandler=TRUE,
> processWarnings=TRUE, resetConsole=TRUE,
> ignoreRestartContexts=FALSE) at errors.c:719
> #1 0x00002aaaaab77e5d in verrorcall_dflt (call=0x609d78,
> format=0x2aaaaace4a4d "%s", ap=0x7fffa13a94c0)
> at errors.c:516
> #2 0x00002aaaaab7814a in Rf_errorcall (call=0x609d78,
> format=0x2aaaaace4a4d "%s") at errors.c:551
> #3 0x00002aaaaab78347 in Rf_error (format=0x2aaaaace42da "could not
> find function \"%s\"") at errors.c:578
> #4 0x00002aaaaab708e5 in Rf_findFun (symbol=0xc64f20, rho=0x649fa0) at
> envir.c:1244
> #5 0x0000000000400e0c in bar1 () at RNamedCall.c:54
> #6 0x0000000000400d59 in main (argc=1, argv=0x7fffa13ab838) at
> RNamedCall.c:16
> 8<------------------------
>
> And then stepping into line 719 generates the segfault:
> 8<------------------------
> (gdb) s
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x00002aaaaab701ce in Rf_findVar (symbol=0x6c12b8, rho=0x0) at envir.c:998
> 998 if (TYPEOF(rho) == NILSXP)
> 8<------------------------
>
> I believe this is happening because findFun() was not executed inside a
> valid context, and therefore R_ToplevelContext->cjmpbuf is invalid.
>
> My question is -- is the above an abuse of findFun() by RNamedCall.c
> (meaning I should avoid the same pattern)? Or maybe it should be wrapped
> in something similar to R_ToplevelExec?
>
> ==========================
>
> On a related note, I found during my PL/R debugging that the segfault
> was causing the same console based, interactive, "*** caught segfault
> ***" logic to execute. I was able to confirm that R_Interactive was set
> to TRUE in my PL/R session.
>
> It seems that Rf_initEmbeddedR() sets R_Interactive to TRUE and depends
> on the output of isatty() to change it to FALSE in Rf_initialize_R() if
> there is no tty. Unfortunately, the most common methods for starting
> Postgres leave the tty attached (stdout and stderr are directed to the
> log file). I ended up explicitly writing "R_Interactive = FALSE" just
> after running Rf_initEmbeddedR() -- is this a safe and reasonable thing
> to do?
>
> Thanks,
>
> Joe
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
--
Byron Ellis (byron.ellis at gmail.com)
"Oook" -- The Librarian
More information about the R-devel
mailing list