[Rd] proper use of reg.finalizer to close connections

Murat Tasan mmuurr at gmail.com
Mon Oct 27 03:35:53 CET 2014


Ah, thanks for the ls() vs names() tip!
(But sadly, it didn't solve the issue... )

So, after some more tinkering, I believe the finalizer is being called
_sometimes_.
I changed the reg.finalizer(...) call to just this:

reg.finalizer(.CONNS, function(x) print("foo"), onexit  = TRUE)

Now, when I load the package and detach(..., unload = TRUE), nothing prints.
And when I quit, nothing prints.

If I, however, create an environment on the workspace, like so:
> e <- new.env(parent = emptyenv())
> reg.finalizer(e, function(x) print("bar"), onexit = TRUE)
When I quit (or rm(e)), "bar" is printed.
But no "foo" (corresponding to same sequence of code, just in the
package instead).

BUT(!), when I _install_ the package, "foo" is printed at the end of
the "**testing if installed package can be loaded" installation
segment.
So, somehow the R script that tests for package loading/unloading is
triggering the finalizer (which is good).
Yet, I cannot seem to trigger it myself when either quitting or
forcing a package unload (which is bad).

Any ideas why the installation script would successfully trigger a
finalizer while standard unloading or quitting wouldn't?

Cheers and thanks!

-m

On Sun, Oct 26, 2014 at 8:03 PM, Gábor Csárdi <csardi.gabor at gmail.com> wrote:
> Hmmm, I guess you will want to put the actual objects that represent
> the connections into the environment, at least this seems to be the
> easiest to me. Btw. you need ls() to list the contents of an
> environment, instead of names(). E.g.
>
> e <- new.env()
> e$foo <- 10
> e$bar <- "aaa"
> names(e)
> #> NULL
> ls(e)
> #> [1] "bar" "foo"
> reg.finalizer(e, function(x) { print(ls(x)) })
> #> NULL
> rm(e)
> gc()
> #> [1] "bar" "foo"
> #>           used (Mb) gc trigger  (Mb) max used  (Mb)
> #> Ncells 1528877 81.7    2564037 137.0  2564037 137.0
> #> Vcells 3752538 28.7    7930384  60.6  7930356  60.6
>
> More precisely, you probably want to represent each connection as a
> separate environment, with its own finalizer. Hope this helps,
> Gabor
>
> On Sun, Oct 26, 2014 at 9:49 PM, Murat Tasan <mmuurr at gmail.com> wrote:
>> Hi all, I have a question about finalizers...
>> I have a package that manages state for a few connections, and I'd
>> like to ensure that these connections are 'cleanly' closed upon either
>> (i) R quitting or (ii) an unloading of the package.
>> So, in a pared-down example package with a single R file, it looks
>> something like:
>>
>> ##### BEGIN PACKAGE CODE #####
>> .CONNS <- new.env(parent = emptyenv())
>> .CONNS$resource1 <- NULL
>> .CONNS$resource2 <- NULL
>> ## some more .CONNS resources...
>>
>> reg.finalizer(.CONNS, function(x) sapply(names(x), disconnect), onexit = TRUE)
>>
>> connect <- function(x) {
>>   ## here lies code to connect and update .CONNS[[x]]
>> }
>> disconnect <- function(x) {
>>   print(sprintf("disconnect(%s)", x))
>>   ## here lies code to disconnect and update .CONNS[[x]]
>> }
>> ##### END PACKAGE CODE #####
>>
>> The print(...) statement in disconnect(...) is there as a trace, as I
>> hoped that I'd see disconnect(...) being called when I quit (or
>> detach(..., unload = TRUE)).
>> But, it doesn't appear that disconnect(...) is ever called when the
>> package (and .CONNS) falls out of memory/scope (and I ran gc() after
>> detach(...), just to be sure).
>>
>> In a second 'shot-in-the-dark' attempt, I placed the reg.finalizer
>> call inside an .onLoad function, but that didn't seem to work, either.
>>
>> I'm guessing my use of reg.finalizer is way off-base here... but I
>> cannot infer from the reg.finalizer man page what I might be doing
>> wrong.
>> Is there a way to see, at the R-system level, what functions have been
>> registered as finalizers?
>>
>> Thanks for any pointers!
>>
>> -Murat
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list