[Rd] closeAllConnections() can really mess things up

Henrik Bengtsson henrik.bengtsson at gmail.com
Sun Oct 30 19:38:07 CET 2016

This is what I get on R 3.3.1 on Linux:

> con1 <- textConnection("foo1", open = "w")
> print(con1)
     description            class             mode             text
          "foo1" "textConnection"              "w"           "text"
          opened         can read        can write
        "opened"             "no"            "yes"

> closeAllConnections()
> con2 <- textConnection("foo2", open = "w")

## Hmm... at this point, con1 point to con2.

> print(con1)
     description            class             mode             text
          "foo2" "textConnection"              "w"           "text"
          opened         can read        can write
        "opened"             "no"            "yes"

> all.equal(con2, con1)
[1] TRUE

Hmm... that looks it could potentially mess up things badly if some
code / user calls closeAllConnections(), then other connections are
opened after that, and then there's code (e.g. via promises or
finalizers) that tries to write to the original connections (resulting
in writing to the new ones).

I'm not sure how one can protect oneself against this.  One approach
that could lower the risk for mistakes is to record a checksum for the
connection (think digest::digest(summary(con1))) when the connection
is first opened and then each time one tried to read or write to the
connect, one validate against this again.

I can see how this could happen if each connection is referenced via
an integer index internally.

I discovered this in a case where the R session terminates (for
unknown reasons) and then calls sys.save.image().  sys.save.image()
calls closeAllConnections() and then save.image().   The latter
triggered promises / delayed assignments to be resolved.  Then each of
those tries to access their previously assigned connections.  At this
point, those are now all closed, but the promises doesn't know and
instead tries to read their connections.  At least the first one will
try to access the now only open connection, which is the one
save.image() opened.  In my case, they tried to read so they failed.


More information about the R-devel mailing list