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