Skip to content

Strange behavior when assigning values in Environment, due to GC #780

@wch

Description

@wch

I've been running into a very hard-to-debug problem which I believe is due to a GC during assignment to an Environment. In some cases, the result of assignment into an Environment has the wrong type, and in other cases, the Environment somehow gets lost.

Here is an example to run in a clean R session:

library(Rcpp)
cppFunction(
  code = '
  Environment f() {
    Environment env = Function("new.env")();
    env["A"] = "a";
    env["B"] = "b";
    env["C"] = "c";
    env["FOO"] = "foo";
    return env;
  }
  '
)

gctorture(TRUE)
e <- f()
gctorture(FALSE)
e$A
e$B
e$C
e$FOO

When I run this on my Mac, here's what it prints out for the last commands:

> gctorture(TRUE)
> e <- f()
> gctorture(FALSE)
> e$A
[1] "a"
> e$B
<CHARSXP: "B">
> e$C
[1] "c"
> e$FOO
<CHARSXP: "FOO">

Inspecting the objects gives this:

> .Internal(inspect(e$A))
@7fd168ce9c68 16 STRSXP g1c1 [MARK,NAM(2)] (len=1, tl=0)
  @7fd168868598 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "a"
> .Internal(inspect(e$B))
@7fd168ce9c98 09 CHARSXP g1c1 [MARK,NAM(2),gp=0x61] [ASCII] [cached] "B"

If I run the code a second time, then the results turn out normal. This is the output from a second run:

> gctorture(TRUE)
> e <- f()
> gctorture(FALSE)
> e$A
[1] "a"
> e$B
[1] "b"
> e$C
[1] "c"
> e$FOO
[1] "foo"

I get the exact same result when I run the same code in the r-base Docker image. To reproduce:

docker run --rm -ti r-base
install.packages('Rcpp')
# Now run the code from above

When I run the same code in a custom build of R-devel with PROTECTCHECK defined, I get something else weird:

....
> gctorture(TRUE)
> e <- f()
> gctorture(FALSE)
> e$A
Error: object 'e' not found
> e$B
Error: object 'e' not found
> e$C
Error: object 'e' not found
> e$FOO
Error: object 'e' not found

e simply never gets assigned.


If the strings get wrapped with CharacterVector(), then the problem doesn't happen. Unlike the code above, this code works fine:

library(Rcpp)
cppFunction(
  code = '
  Environment f() {
    Environment env = Function("new.env")();
    env["A"] = CharacterVector("a");
    env["B"] = CharacterVector("b");
    env["C"] = CharacterVector("c");
    env["FOO"] = CharacterVector("foo");
    return env;
  }
  '
)

gctorture(TRUE)
e <- f()
gctorture(FALSE)
e$A
e$B
e$C
e$FOO

In my particular case, the problem happens with httpuv. When I run the PROTECTCHECK build of R, I get this error in some httpuv code when it assigns a string to an environment:

Error: GC encountered a node (0x5611e376c9d0) with type FREESXP (was STRSXP) at memory.c:1696

The code in question looks like this:

   env["rook.version"] = "1.1-0"

And many other places where a string is assigned results in the same error message. Wrapping all of them in CharacterVector() seems to make the error go away.


If it would help, I can provide the Dockerfile used to create the build of R with PROTECTCHECK defined.

> sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 3.4.2 (2017-09-28)
 os       macOS High Sierra 10.13.1   
 system   x86_64, darwin15.6.0        
 ui       X11                         
 language (EN)                        
 collate  en_US.UTF-8                 
 tz       <NA>                        
 date     2017-12-01                  

─ Packages ───────────────────────────────────────────────────────────────────
 package     * version date       source        
 clisymbols    1.2.0   2017-05-21 CRAN (R 3.4.0)
 Rcpp        * 0.12.14 2017-11-23 CRAN (R 3.4.3)
 sessioninfo   1.0.0   2017-06-21 CRAN (R 3.4.1)
 withr         2.1.0   2017-11-01 CRAN (R 3.4.2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions