[Rd] Child thread libR.so

Ryan C Metzger metzger.rc at gmail.com
Tue Aug 25 18:54:46 CEST 2015


Simon,
Ah, thank you! quiet right. For anyone searching for this in the
future, I changed my init fuction to:

---------- SNIP ----------------
void init_r() {
    SEXP aperm_function;

    /* this is our version of Rf_initEmbeddedR where we disable stack
checking */
    const char *init_argv[] = {"MyFront", "--vanilla", "--slave"};
    Rf_initialize_R(sizeof (init_argv) / sizeof (init_argv[0]),
(char**) init_argv);

    /* Disable stack limit checking since it is incompatible being
loaded on a child thread
     */
    R_CStackLimit = (uintptr_t)-1;

    R_Interactive = TRUE;  /* Rf_initialize_R set this based on isatty */
    setup_Rmainloop();
    /* end of Rf_initEmbeddedR */

    /*
     * transposeVector above uses the R builtin function aperm instead of
     * looking it up every time we need deal with transposing a multidimensional
     * intput/output look it up once here and save it off
     */
    aperm_function = findFun(install("aperm"), R_GlobalEnv);
    if (aperm_function == NULL || aperm_function == R_NilValue ||
aperm_function == R_UnboundValue) {
        aperm_function = NULL;
    } else {
        aperm_expression = PROTECT(allocVector(LANGSXP, 2));

        SETCAR(aperm_expression, aperm_function);
    }
}
---------- SNIP ----------------

This now behaves appropriately from a child thread in my custom front end.

thank you again Simon,
Ryan

> Ryan,
>
> if you read the piece you quoted from more carefully, you'll notice it says "Rf_initialize_R" - which is quite critical in this matter.
>
> Cheers,
> Simon
>
>
> On Aug 24, 2015, at 9:18 AM, Ryan C Metzger <metzger.rc at gmail.com> wrote:
>
>> I did some poking around with GDB and confirmed that the advice of
>> setting R_CStackLimit after init, which is echoed in the "threading
>> issues" section of the R-exts help document, isn't entirely useful
>> because init apparently loads the main package which trips over the
>> broken stack checking.
>>
>> Stack trace:
>>
>> #0  R_SignalCStackOverflow (usage=140732197147604) at errors.c:81
>> #1  0x00002aaaab0625b7 in Rf_eval (e=0x1b7592a8, rho=0x1b753960) at eval.c:545
>> #2  0x00002aaaab0871ca in R_ReplFile (fp=0x1b69a830, rho=0x1b753960)
>> at main.c:98
>> #3  0x00002aaaab087a27 in setup_Rmainloop () at main.c:861
>> #4  0x00002aaaab14a98b in Rf_initEmbeddedR (argc=<value optimized
>> out>, argv=<value optimized out>) at Rembedded.c:63
>>
>> On Thu, Aug 20, 2015 at 1:21 PM, Ryan C Metzger <metzger.rc at gmail.com> wrote:
>>> So I'm working on a custom front end to R, in one mode of the front
>>> end I dynamically load libR.so into a child worker thread. I'm very
>>> careful to make sure it is loaded by a single thread and loaded only
>>> once, but since it is a child thread it violates assumptions made by
>>> the stack size checking inside of R and I get innumerable errors along
>>> the lines of
>>>
>>> Error: C stack usage  140732526462740 is too close to the limit
>>>
>>> Digging through this email list (and I also found similar things out
>>> on google) I found the following advice from 2009
>>>
>>> ---------------------------------------- SNIP
>>> ------------------------------------------------------------------------------
>>>> Hi everyone!
>>>>  I meet one problem when embedding R in C code, when I run the the
>>>> R code in one child thread ,
>>>>  it always print error info:
>>>>   Error: C stack usage is too close to the limit
>>>>
>>>>  I also try to set R_CStackLimit = (uintptr_t)-1 to disable the C
>>>> stack check as the R-exts doc say,
>>>>  but it still does not work, the error info still exist.
>>>>
>>>
>>> That is the way to do it (and other project use it successfully) - the
>>> fact that it doesn't work means that you probably do it at the wrong
>>> place (you must set it *after* Rf_initialize_R).
>>>
>>> Cheers,
>>> Simon
>>> ---------------------------------------- SNIP
>>> ------------------------------------------------------------------------------
>>>
>>> my code is as follows
>>>
>>> ---------------------------------------- SNIP
>>> ------------------------------------------------------------------------------
>>> void init_r() {
>>>    SEXP aperm_function;
>>>
>>>    const char *init_argv[] = {"MyFront", "--vanilla", "--slave"};
>>>    Rf_initEmbeddedR(sizeof (init_argv) / sizeof (init_argv[0]),
>>> (char**) init_argv);
>>>
>>>    R_CStackLimit = (uintptr_t)-1;
>>>
>>>    /*
>>>     * transposeVector above uses the R builtin function aperm instead of
>>>     * looking it up every time we need deal with transposing a multidimensional
>>>     * intput/output look it up once here and save it off
>>>     */
>>>    aperm_function = findFun(install("aperm"), R_GlobalEnv);
>>>    if (aperm_function == NULL || aperm_function == R_NilValue ||
>>> aperm_function == R_UnboundValue) {
>>>        aperm_function = NULL;
>>>    } else {
>>>        aperm_expression = PROTECT(allocVector(LANGSXP, 2));
>>>
>>>        SETCAR(aperm_expression, aperm_function);
>>>    }
>>> }
>>> ---------------------------------------- SNIP
>>> ------------------------------------------------------------------------------
>>>
>>> but as I say I still get the error and it seems like the call to
>>> Rf_initEmbeddedR just never returns. As an experiment I edited
>>> config.h.in and removed the define for HAVE_GETRLIMIT and recompiled,
>>> thus compiling out the stack checking mechanism entirely. Then
>>> everything worked great!, so I know it's the stack checking mechanism
>>> from a child thread that is falling to pieces. So what I have in mind
>>> is looking to fix this mechanism so that it works from a child thread
>>> if the pthread library is available and submitting a patch. My
>>> question is two fold, 1. Is there a way to get this to work without a
>>> code change ( I'd like to be able to offer my front end stand alone
>>> and not have to bundle R with it ) 2. If I do come up with a diff, how
>>> do I go about submitting it back to the r foundation?
>>>
>>>
>>> for completeness the version of R I am using
>>>
>>>> version
>>>               _
>>> platform       x86_64-unknown-linux-gnu
>>> arch           x86_64
>>> os             linux-gnu
>>> system         x86_64, linux-gnu
>>> status
>>> major          3
>>> minor          2.1
>>> year           2015
>>> month          06
>>> day            18
>>> svn rev        68531
>>> language       R
>>> version.string R version 3.2.1 (2015-06-18)
>>> nickname       World-Famous Astronaut
>>>
>>> compiled from source with configure options
>>> head R-3.2.1/config.log
>>> This file contains any messages produced by compilers while
>>> running configure, to aid debugging if configure makes a mistake.
>>>
>>> It was created by R configure 3.2.1, which was
>>> generated by GNU Autoconf 2.69.  Invocation command line was
>>>
>>>  $ ./configure --prefix /u/rmetzger/linux_R_vanilla --enable-R-shlib
>>>
>>> ## --------- ##
>>> ## Platform. ##
>>>
>>> thank you!
>>> Ryan



More information about the R-devel mailing list