[Rd] interesting connection / finalizer bug?

Martin Morgan mtmorgan at fhcrc.org
Fri Jan 6 09:16:00 CET 2012


This

setOldClass(c("file", "connection"))
.A <- setRefClass("A", fields=list(con="connection"),
                   methods=list(
                     finalize = function() {
                         if (isOpen(con)) close(con)
                     }))

f <- tempdir()
a <- .A$new(con=file(f, "rb"))
close(a$con)
a <- .A$new(con=file(f, "rb"))
bin <- readBin(a$con, raw(), as.integer(1e8))

crashes (hangs, usually) at the last line, with valgrind saying

==14875== Invalid read of size 8
==14875==    at 0x4EB23DA: do_readbin (connections.c:3678)
==14875==    by 0x4F795E4: do_internal (names.c:1236)
==14875==    by 0x4F15F63: Rf_eval (eval.c:471)
==14875==    by 0x4F18BA7: do_begin (eval.c:1422)
==14875==    by 0x4F15F63: Rf_eval (eval.c:471)
==14875==    by 0x4F16F0C: Rf_applyClosure (eval.c:840)
==14875==    by 0x4F16276: Rf_eval (eval.c:515)
==14875==    by 0x4F19939: do_set (eval.c:1726)
==14875==    by 0x4F15F63: Rf_eval (eval.c:471)
==14875==    by 0x4F5EF6C: Rf_ReplIteration (main.c:256)
==14875==    by 0x4F5F159: R_ReplConsole (main.c:305)
==14875==    by 0x4F607B8: run_Rmainloop (main.c:986)
==14875==  Address 0x907f1d8 is 136 bytes inside a block of size 448 free'd
==14875==    at 0x4C25F7B: free (in 
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==14875==    by 0x4EB0282: con_destroy (connections.c:3086)
==14875==    by 0x4EB03B3: do_close (connections.c:3105)
==14875==    by 0x4F795E4: do_internal (names.c:1236)
==14875==    by 0x4F15F63: Rf_eval (eval.c:471)
==14875==    by 0x4F19D7F: Rf_evalList (eval.c:1840)
==

A little more revealing, with two surprises noted, is

 > f <- tempdir()
 > a <- .A$new(con=file(f, "rb"))
 > close(a$con)
 > a <- .A$new(con=file(f, "rb"))
 > gc() ## run finalizer -- should complain about invalid connection!
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells 205579 11.0     407500 21.8   350000 18.7
Vcells 162784  1.3     786432  6.0   558828  4.3
 > bin <- readBin(a$con, raw(), as.integer(1e8))  ## a$con should be ok!
Error in readBin(a$con, raw(), as.integer(1e+08)) : invalid connection

Presumably the example without the explicit garbage collection results 
from a garbage collection triggered after the connection has been tested 
for validity. This is not a finalizer bug, as the following elicits the 
same behavior

invisible(gcinfo(TRUE))
f <- tempdir()

e <- new.env()
reg.finalizer(e, function(e) tryCatch({
     if (isOpen(e$con)) close(e$con)
}))
e$con <- file(f, "rb")
close(e$con)

e <- new.env()
e$con <- file(f, "rb")
bin <- readBin(e$con, raw(), as.integer(1e8))

 > sessionInfo()
R Under development (unstable) (2012-01-04 r58051)
Platform: x86_64-unknown-linux-gnu (64-bit)

locale:
  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
  [7] LC_PAPER=C                 LC_NAME=C
  [9] LC_ADDRESS=C               LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base


-- 
Computational Biology
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109

Location: M1-B861
Telephone: 206 667-2793



More information about the R-devel mailing list